diff options
Diffstat (limited to 'deps')
24 files changed, 6923 insertions, 0 deletions
diff --git a/deps/netlink/LICENSE b/deps/netlink/LICENSE new file mode 100644 index 0000000..14e2f77 --- /dev/null +++ b/deps/netlink/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/deps/netlink/README b/deps/netlink/README new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/deps/netlink/README diff --git a/deps/netlink/c_src/.gitignore b/deps/netlink/c_src/.gitignore new file mode 100644 index 0000000..d6ff91a --- /dev/null +++ b/deps/netlink/c_src/.gitignore @@ -0,0 +1,2 @@ +*~ +*.o diff --git a/deps/netlink/c_src/Makefile b/deps/netlink/c_src/Makefile new file mode 100644 index 0000000..984e8dc --- /dev/null +++ b/deps/netlink/c_src/Makefile @@ -0,0 +1,13 @@ +.PHONY: libnl + +PRIVDIR := ../priv + +all : $(PRIVDIR)/netlink_drv.so + +override CFLAGS += -fpic -shared + +$(PRIVDIR)/netlink_drv.so : netlink_drv.o + $(CC) -shared -fpic $(LDFLAGS) -o $@ $^ + +clean: + $(RM) -f $(PRIVDIR)/netlink_drv.so netlink_drv.o diff --git a/deps/netlink/c_src/netlink_drv.c b/deps/netlink/c_src/netlink_drv.c new file mode 100644 index 0000000..15da7e5 --- /dev/null +++ b/deps/netlink/c_src/netlink_drv.c @@ -0,0 +1,727 @@ +/****** BEGIN COPYRIGHT ******************************************************* + * + * Copyright (C) 2012 Feuerlabs, Inc. All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + ****** END COPYRIGHT ********************************************************/ +// +// Netlink driver +// + +#include <stdio.h> +#include <stdarg.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <asm/types.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> + +#include "erl_driver.h" + +#define ATOM(NAME) am_ ## NAME +#define INIT_ATOM(NAME) am_ ## NAME = driver_mk_atom(#NAME) + +// Hack to handle R15 driver used with pre R15 driver +#if ERL_DRV_EXTENDED_MAJOR_VERSION == 1 +typedef int ErlDrvSizeT; +typedef int ErlDrvSSizeT; +#endif + +#if (ERL_DRV_EXTENDED_MAJOR_VERSION > 2) || ((ERL_DRV_EXTENDED_MAJOR_VERSION == 2) && (ERL_DRV_EXTENDED_MINOR_VERSION >= 1)) +#define SEND_TERM(ctx, to, message, len) erl_drv_send_term((ctx)->dport,(to),(message),(len)) +#else +#define SEND_TERM(ctx, to, message, len) driver_send_term((ctx)->port,(to),(message),(len)) +#endif + +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +#define PORT_CONTROL_BINARY + +#define INT_EVENT(ptr) ((int)((long)(ptr))) + +typedef struct _nl_ctx_t { + ErlDrvPort port; + ErlDrvTermData dport; + ErlDrvTermData owner; + ErlDrvEvent fd; // netlink socket + int protocol; // netlink protocol + int active; + int is_selecting; + int is_sending; + void* nlbuf; + size_t nlbuf_len; +} nl_ctx_t; + +#define CMD_ADD_MEMBERSHIP 1 +#define CMD_DROP_MEMBERSHIP 2 +#define CMD_ACTIVE 3 +#define CMD_DEBUG 4 +#define CMD_SET_RCVBUF 5 +#define CMD_SET_SNDBUF 6 +#define CMD_GET_RCVBUF 7 +#define CMD_GET_SNDBUF 8 +#define CMD_GET_SIZEOF 9 + + +#define CTL_OK 0 +#define CTL_INT 1 +#define CTL_PAIR 2 +#define CTL_BIN 3 +#define CTL_LIST 4 +#define CTL_ERR 255 +#define CTL_STRERR 254 + +#define MIN_NL_BUFSIZE (32*1024) +#define MAX_NL_BUFSIZE (512*1024) + +#define MAX_VSIZE 16 + +ErlDrvTermData am_ok; +ErlDrvTermData am_error; +ErlDrvTermData am_undefined; +ErlDrvTermData am_true; +ErlDrvTermData am_false; +ErlDrvTermData am_nl_data; + +#define push_atom(atm) do { \ + message[i++] = ERL_DRV_ATOM; \ + message[i++] = (atm); \ + } while(0) + +#define push_port(prt) do { \ + message[i++] = ERL_DRV_PORT; \ + message[i++] = (prt); \ + } while(0) + +#define push_pid(pid) do { \ + message[i++] = ERL_DRV_PID; \ + message[i++] = (pid); \ + } while(0) + +#define push_bin(buf,len) do { \ + message[i++] = ERL_DRV_BUF2BINARY; \ + message[i++] = (ErlDrvTermData)(buf); \ + message[i++] = (ErlDrvTermData)(len); \ + } while(0) + +#define push_nil() do { \ + message[i++] = ERL_DRV_NIL; \ + } while(0) + +#define push_string(str) do { \ + message[i++] = ERL_DRV_STRING; \ + message[i++] = (ErlDrvTermData) (str); \ + message[i++] = strlen(str); \ + } while(0) + +#define push_int(val) do { \ + message[i++] = ERL_DRV_INT; \ + message[i++] = (val); \ + } while(0) + +#define push_tuple(n) do { \ + message[i++] = ERL_DRV_TUPLE; \ + message[i++] = (n); \ + } while(0) + +#define push_list(n) do { \ + message[i++] = ERL_DRV_LIST; \ + message[i++] = (n); \ + } while(0) + + +ErlDrvEntry nl_drv_entry; + +static inline uint32_t get_uint32(uint8_t* ptr) +{ + uint32_t value = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | (ptr[3]<<0); + return value; +} + +static inline int32_t get_int32(uint8_t* ptr) +{ + uint32_t value = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | (ptr[3]<<0); + return (int32_t) value; +} + +static inline uint16_t get_uint16(uint8_t* ptr) +{ + uint16_t value = (ptr[0]<<8) | (ptr[1]<<0); + return value; +} + +static inline uint8_t get_uint8(uint8_t* ptr) +{ + return ptr[0]; +} + +static inline int8_t get_int8(uint8_t* ptr) +{ + return (int8_t) ptr[0]; +} + +static inline void put_uint16(uint8_t* ptr, uint16_t v) +{ + ptr[0] = v>>8; + ptr[1] = v; +} + +static inline void put_uint32(uint8_t* ptr, uint32_t v) +{ + ptr[0] = v>>24; + ptr[1] = v>>16; + ptr[2] = v>>8; + ptr[3] = v; +} + +static int nl_drv_init(void); +static void nl_drv_finish(void); +static void nl_drv_stop(ErlDrvData); +static void nl_drv_output(ErlDrvData,char*,ErlDrvSizeT); +#if 0 +static void nl_drv_outputv(ErlDrvData, ErlIOVec*); +#endif +static void nl_drv_ready_input(ErlDrvData, ErlDrvEvent); +static void nl_drv_ready_output(ErlDrvData data, ErlDrvEvent event); +static ErlDrvData nl_drv_start(ErlDrvPort, char* command); +static ErlDrvSSizeT nl_drv_ctl(ErlDrvData,unsigned int,char*,ErlDrvSizeT,char**,ErlDrvSizeT); +static void nl_drv_timeout(ErlDrvData); +static void nl_drv_stop_select(ErlDrvEvent event, void* arg); + +#define DLOG_DEBUG 7 +#define DLOG_INFO 6 +#define DLOG_NOTICE 5 +#define DLOG_WARNING 4 +#define DLOG_ERROR 3 +#define DLOG_CRITICAL 2 +#define DLOG_ALERT 1 +#define DLOG_EMERGENCY 0 +#define DLOG_NONE -1 + +#ifndef DLOG_DEFAULT +#define DLOG_DEFAULT DLOG_NONE +#endif + +#define DLOG(level,file,line,args...) do { \ + if (((level) == DLOG_EMERGENCY) || \ + ((debug_level >= 0) && ((level) <= debug_level))) { \ + emit_log((level),(file),(line),args); \ + } \ + } while(0) + +#define DEBUGF(args...) DLOG(DLOG_DEBUG,__FILE__,__LINE__,args) +#define INFOF(args...) DLOG(DLOG_INFO,__FILE__,__LINE__,args) +#define NOTICEF(args...) DLOG(DLOG_NOTICE,__FILE__,__LINE__,args) +#define WARNINGF(args...) DLOG(DLOG_WARNING,__FILE__,__LINE__,args) +#define ERRORF(args...) DLOG(DLOG_ERROR,__FILE__,__LINE__,args) +#define CRITICALF(args...) DLOG(DLOG_CRITICAL,__FILE__,__LINE__,args) +#define ALERTF(args...) DLOG(DLOG_ALERT,__FILE__,__LINE__,args) +#define EMERGENCYF(args...) DLOG(DLOG_EMERGENCY,__FILE__,__LINE__,args) + +static int debug_level = DLOG_DEFAULT; + +static void emit_log(int level, char* file, int line, ...) +{ + va_list ap; + char* fmt; + + if ((level == DLOG_EMERGENCY) || + ((debug_level >= 0) && (level <= debug_level))) { + int save_errno = errno; + va_start(ap, line); + fmt = va_arg(ap, char*); + fprintf(stderr, "%s:%d: ", file, line); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\r\n"); + va_end(ap); + errno = save_errno; + } +} + +/* general control reply function */ +static ErlDrvSSizeT ctl_reply(int rep, void* buf, ErlDrvSizeT len, + char** rbuf, ErlDrvSizeT rsize) +{ + char* ptr; + + if ((len+1) > rsize) { +#ifdef PORT_CONTROL_BINARY + ErlDrvBinary* bin = driver_alloc_binary(len+1); + if (bin == NULL) + return -1; + ptr = bin->orig_bytes; + *rbuf = (char*) bin; +#else + if ((ptr = driver_alloc(len+1)) == NULL) + return -1; + *rbuf = ptr; +#endif + } + else + ptr = *rbuf; + *ptr++ = rep; + memcpy(ptr, buf, len); + return len+1; +} + +static void* nl_realloc_buffer(nl_ctx_t* ctx, size_t len) +{ + if (ctx->nlbuf_len < len) { + ctx->nlbuf = driver_realloc(ctx->nlbuf, NLMSG_SPACE(len)); + ctx->nlbuf_len = len; + } + return ctx->nlbuf; +} + +static int nl_drv_init(void) +{ + INIT_ATOM(ok); + INIT_ATOM(error); + INIT_ATOM(undefined); + INIT_ATOM(true); + INIT_ATOM(false); + INIT_ATOM(nl_data); + return 0; +} + +static void nl_drv_finish(void) +{ +} + +static void nl_drv_stop(ErlDrvData d) +{ + nl_ctx_t* ctx = (nl_ctx_t*) d; + + if (ctx) { + if (ctx->is_selecting) + driver_select(ctx->port, ctx->fd, ERL_DRV_READ, 0); + if (ctx->is_sending) + driver_select(ctx->port, ctx->fd, ERL_DRV_WRITE, 0); + driver_select(ctx->port, ctx->fd, ERL_DRV_USE, 0); + driver_free(ctx); + } +} + +static void nl_drv_output(ErlDrvData d, char* buf,ErlDrvSizeT len) +{ + nl_ctx_t* ctx = (nl_ctx_t*) d; + int n; + struct nlmsghdr* nlh = (struct nlmsghdr*) buf; + + if (!NLMSG_OK(nlh, len)) { + DEBUGF("netlink_drv: data not OK"); + } + else { + DEBUGF("netlink_drv: output len=%d, type=%d, seq=%d, pid=%d", + nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_seq, nlh->nlmsg_pid); + if ((n = driver_sizeq(ctx->port)) > 0) { + driver_enq(ctx->port, buf, len); + DEBUGF("netlink_drv_output: put on queue pending=%d", n+len); + } + else { // try send directly + struct sockaddr_nl dest_addr; + struct iovec iov; + struct msghdr msg; + + memset(&msg, 0, sizeof(msg)); + memset(&dest_addr, 0, sizeof(dest_addr)); + + dest_addr.nl_family = AF_NETLINK; + dest_addr.nl_pid = 0; // to kernel + dest_addr.nl_groups = 0; // unicast + + iov.iov_base = (void*) buf; + iov.iov_len = len; + + msg.msg_name = (void*) &dest_addr; + msg.msg_namelen = sizeof(dest_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + n = sendmsg(INT_EVENT(ctx->fd), &msg, 0); + if (n < 0) { + ERRORF("write error=%s", strerror(errno)); + if ((errno == EAGAIN) || (errno = ENOBUFS)) { + DEBUGF("netlink_drv: put on queue", n); + driver_enq(ctx->port, buf, len); + driver_select(ctx->port, ctx->fd, ERL_DRV_WRITE, 1); + ctx->is_sending = 1; + } + } + } + } +} + + +// netlink socket triggered process data +static void nl_drv_ready_input(ErlDrvData d, ErlDrvEvent event) +{ + nl_ctx_t* ctx = (nl_ctx_t*) d; + struct sockaddr_nl src_addr; + struct iovec iov; + struct msghdr msg; + struct nlmsghdr* nlh; + int n; + int part = 0; + int recv_count = 10; + + DEBUGF("nl_drv_ready_input"); + +again: + if (!--recv_count) + return; + memset(&iov, 0, sizeof(iov)); + memset(&msg, 0, sizeof(msg)); + memset(&src_addr, 0, sizeof(src_addr)); + + nlh = nl_realloc_buffer(ctx, MIN_NL_BUFSIZE); + + iov.iov_base = (void*) nlh; + iov.iov_len = ctx->nlbuf_len; + msg.msg_name = (void*) &src_addr; + msg.msg_namelen = sizeof(src_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + if ((n = recvmsg(INT_EVENT(ctx->fd), &msg, 0)) < 0) { + if (errno == EAGAIN) + return; + // send error to erlang ? + WARNINGF("nl_drv_read_input: read error=%s", strerror(errno)); + } + else if (n == 0) { + WARNINGF("nl_drv_read_input: read eof?"); + } + else { + ErlDrvTermData message[16]; + + while(NLMSG_OK(nlh, n)) { + int i = 0; + // {nl_data, <port>, <data>} + push_atom(ATOM(nl_data)); + push_port(ctx->dport); + push_bin((char*)nlh, nlh->nlmsg_len); + push_tuple(3); + DEBUGF("nl_drv_read_input: part = %d", part); + part++; + if (ctx->active) { + SEND_TERM(ctx, ctx->owner, message, i); + if (ctx->active > 0) { + ctx->active--; + if (ctx->active == 0) { + ctx->is_selecting = 0; + driver_select(ctx->port, ctx->fd, ERL_DRV_READ, 0); + } + } + } + nlh = NLMSG_NEXT(nlh, n); + } + goto again; + } +} + +static void nl_drv_ready_output(ErlDrvData d, ErlDrvEvent event) +{ + nl_ctx_t* ctx = (nl_ctx_t*) d; + struct sockaddr_nl dest_addr; + int vsize; + SysIOVec* iovp; + struct msghdr msg; + int n; + + DEBUGF("nl_drv_ready_output called"); + + if (ctx->fd != event) { + DEBUGF("nl_drv_ready_output bad event"); + return; + } + + if ((iovp = driver_peekq(ctx->port, &vsize)) == NULL) { + driver_select(ctx->port, ctx->fd, ERL_DRV_WRITE, 0); + ctx->is_sending = 0; + return; + } + vsize = vsize > MAX_VSIZE ? MAX_VSIZE : vsize; + + memset(&msg, 0, sizeof(msg)); + memset(&dest_addr, 0, sizeof(dest_addr)); + + dest_addr.nl_family = AF_NETLINK; + dest_addr.nl_pid = 0; // to kernel + dest_addr.nl_groups = 0; // unicast + + msg.msg_name = (void*) &dest_addr; + msg.msg_namelen = sizeof(dest_addr); + msg.msg_iov = (struct iovec*) iovp; + msg.msg_iovlen = vsize; + + DEBUGF("nl_drv_ready_output: try send vsize=%d", vsize); + n = sendmsg(INT_EVENT(ctx->fd), &msg, 0); + if (n < 0) { + if ((errno == EAGAIN) || (errno == ENOBUFS)) + return; + ERRORF("write error=%s", strerror(errno)); + return; + } + DEBUGF("nl_drv_ready_output: sent %d bytes", n); + if (driver_deq(ctx->port, n) == 0) { + driver_select(ctx->port, ctx->fd, ERL_DRV_WRITE, 0); + ctx->is_sending = 0; + } +} + +static ErlDrvSSizeT nl_drv_ctl(ErlDrvData d,unsigned int cmd,char* buf0, + ErlDrvSizeT len,char** rbuf,ErlDrvSizeT rsize) +{ + uint8_t* buf = (uint8_t*) buf0; + nl_ctx_t* ctx = (nl_ctx_t*) d; + + DEBUGF("nl_drv_ctl cmd=%d", cmd); + + switch(cmd) { + case CMD_ADD_MEMBERSHIP: { + int opt; + if (len != 4) + goto badarg; + opt = get_int32(buf); + if (setsockopt(INT_EVENT(ctx->fd), SOL_NETLINK, + NETLINK_ADD_MEMBERSHIP, + (void*) &opt, sizeof(opt)) < 0) + goto error; + goto ok; + } + case CMD_DROP_MEMBERSHIP: { + int opt; + if (len != 4) + goto badarg; + opt = get_int32(buf); + + if (setsockopt(INT_EVENT(ctx->fd), SOL_NETLINK, + NETLINK_DROP_MEMBERSHIP, + (void*) &opt, sizeof(opt)) < 0) + goto error; + goto ok; + } + + case CMD_SET_RCVBUF: { + int opt; + if (len != 4) + goto badarg; + opt = get_int32(buf); + if (setsockopt(INT_EVENT(ctx->fd), SOL_SOCKET, + SO_RCVBUF, + (void*) &opt, sizeof(opt)) < 0) + goto error; + if (opt > 0) { + // make sure i/o buffer match + nl_realloc_buffer(ctx, (size_t)opt); + } + goto ok; + } + + case CMD_SET_SNDBUF: { + int opt; + if (len != 4) + goto badarg; + opt = get_int32(buf); + if (setsockopt(INT_EVENT(ctx->fd), SOL_SOCKET, + SO_SNDBUF, + (void*) &opt, sizeof(opt)) < 0) + goto error; + if (opt > 0) { + // make sure i/o buffer match + nl_realloc_buffer(ctx, (size_t)opt); + } + goto ok; + } + + case CMD_GET_RCVBUF: { + int opt; + socklen_t optlen; + if (len != 0) + goto badarg; + optlen = sizeof(opt); + opt = get_int32(buf); + if (getsockopt(INT_EVENT(ctx->fd), SOL_SOCKET, + SO_RCVBUF, + (void*) &opt, &optlen) < 0) + goto error; + return ctl_reply(CTL_INT, &opt, sizeof(opt), rbuf, rsize); + } + + case CMD_GET_SNDBUF: { + int opt; + socklen_t optlen; + if (len != 0) + goto badarg; + optlen = sizeof(opt); + opt = get_int32(buf); + if (getsockopt(INT_EVENT(ctx->fd), SOL_SOCKET, + SO_SNDBUF, + (void*) &opt, &optlen) < 0) + goto error; + return ctl_reply(CTL_INT, &opt, sizeof(opt), rbuf, rsize); + } + + case CMD_GET_SIZEOF: { + uint8_t sizes[6]; + + sizes[0] = (uint8_t) sizeof(char); + sizes[1] = (uint8_t) sizeof(short); + sizes[2] = (uint8_t) sizeof(int); + sizes[3] = (uint8_t) sizeof(long); + sizes[4] = (uint8_t) sizeof(long long); + sizes[5] = (uint8_t) sizeof(void*); + return ctl_reply(CTL_LIST, sizes, 6, rbuf, rsize); + } + + case CMD_ACTIVE: { + int active; + + if (len != 4) + goto badarg; + active = get_int32(buf); + if (active) { + if (!ctx->is_selecting) + driver_select(ctx->port, ctx->fd, ERL_DRV_READ, 1); + ctx->is_selecting = 1; + ctx->active = active; + } + else { + if (ctx->is_selecting) + driver_select(ctx->port, ctx->fd, ERL_DRV_READ, 0); + ctx->is_selecting = 0; + ctx->active = 0; + } + goto ok; + break; + } + case CMD_DEBUG: { + if (len != 4) + goto badarg; + debug_level = get_int32(buf); + goto ok; + } + + default: + return -1; + } + +ok: + return ctl_reply(CTL_OK, NULL, 0, rbuf, rsize); +badarg: + errno = EINVAL; +error: { + char* err_str = erl_errno_id(errno); + return ctl_reply(CTL_ERR, err_str, strlen(err_str), rbuf, rsize); +} +} + + +static void nl_drv_timeout(ErlDrvData d) +{ + (void) d; + fprintf(stderr, "nl_drv_timeout called!!!\r\n"); +} + +static void nl_drv_stop_select(ErlDrvEvent event, void* arg) +{ + (void) arg; + DEBUGF("eth_drv: stop_select event=%d", INT_EVENT(event)); + close(INT_EVENT(event)); +} + + +static ErlDrvData nl_drv_start(ErlDrvPort port, char* command) +{ + (void) command; + nl_ctx_t* ctx; + int flags; + int fd; + int protocol; + char* ptr; + char* arg; + struct sockaddr_nl addr; + + ptr = command; + while(*ptr && (*ptr != ' ')) ptr++; // skip command + while(*ptr && (*ptr == ' ')) ptr++; // and blanks + arg = ptr; + while(*ptr && (*ptr >= '0') && (*ptr <= '9')) ptr++; + if ((arg == ptr) || (*ptr != '\0')) { + errno = EINVAL; + return ERL_DRV_ERROR_ERRNO; + } + protocol = atoi(arg); + + if ((fd = socket(PF_NETLINK, SOCK_RAW, protocol)) < 0) + return ERL_DRV_ERROR_ERRNO; + + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + addr.nl_groups = 0; // start with no groups + addr.nl_pid = getpid(); // bind using this pid? + + if (bind(fd, (struct sockaddr* ) &addr, sizeof(addr)) < 0) + return ERL_DRV_ERROR_ERRNO; + + flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + + if (!(ctx = driver_alloc(sizeof(nl_ctx_t)))) + return ERL_DRV_ERROR_ERRNO; + memset(ctx, 0, sizeof(nl_ctx_t)); + ctx->port = port; + ctx->dport = driver_mk_port(port); + ctx->owner = driver_caller(port); + ctx->protocol = protocol; + ctx->fd = (ErlDrvEvent)((long)fd); + + nl_realloc_buffer(ctx, MIN_NL_BUFSIZE); // create i/o buffer + +#ifdef PORT_CONTROL_BINARY + set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); +#endif + + return (ErlDrvData) ctx; +} + +DRIVER_INIT(nl_drv) +{ + ErlDrvEntry* ptr = &nl_drv_entry; + + ptr->driver_name = "netlink_drv"; + ptr->init = nl_drv_init; + ptr->start = nl_drv_start; + ptr->stop = nl_drv_stop; + ptr->output = nl_drv_output; + ptr->ready_input = nl_drv_ready_input; + ptr->ready_output = nl_drv_ready_output; + ptr->finish = nl_drv_finish; + ptr->control = nl_drv_ctl; + ptr->timeout = nl_drv_timeout; +#if 0 + ptr->outputv = nl_drv_outputv; +#endif + ptr->ready_async = 0; + ptr->flush = 0; + ptr->call = 0; + ptr->event = 0; + ptr->extended_marker = ERL_DRV_EXTENDED_MARKER; + ptr->major_version = ERL_DRV_EXTENDED_MAJOR_VERSION; + ptr->minor_version = ERL_DRV_EXTENDED_MINOR_VERSION; + ptr->driver_flags = ERL_DRV_FLAG_USE_PORT_LOCKING; + ptr->process_exit = 0; + ptr->stop_select = nl_drv_stop_select; + + return (ErlDrvEntry*) ptr; +} diff --git a/deps/netlink/include/log.hrl b/deps/netlink/include/log.hrl new file mode 100644 index 0000000..270f06c --- /dev/null +++ b/deps/netlink/include/log.hrl @@ -0,0 +1,44 @@ +%% +%% Log macros +%% +-ifndef(__LOG_HRL__). +-define(__LOG_HRL__, true). + +-compile({parse_transform, lager_transform}). + +%% Lager logging levels +%% debug, info, notice, warning, error, critical, alert, emergency, none. + +-define(debug(Fmt), lager:debug(Fmt)). +-define(debug(Fmt, Args), lager:debug(Fmt, Args)). +-define(debug(Attrs, Fmt, Args), lager:debug(Attrs, Fmt, Args)). + +-define(info(Fmt), lager:info(Fmt)). +-define(info(Fmt, Args), lager:info(Fmt, Args)). +-define(info(Attrs, Fmt, Args), lager:info(Attrs, Fmt, Args)). + +-define(notice(Fmt), lager:notice(Fmt)). +-define(notice(Fmt, Args), lager:notice(Fmt, Args)). +-define(notice(Attrs, Fmt, Args), lager:notice(Attrs, Fmt, Args)). + +-define(warning(Fmt), lager:warning(Fmt)). +-define(warning(Fmt, Args), lager:warning(Fmt, Args)). +-define(warning(Attrs, Fmt, Args), lager:warning(Attrs, Fmt, Args)). + +-define(error(Fmt), lager:error(Fmt)). +-define(error(Fmt, Args), lager:error(Fmt, Args)). +-define(error(Attrs, Fmt, Args), lager:error(Attrs, Fmt, Args)). + +-define(critical(Fmt), lager:critical(Fmt)). +-define(critical(Fmt, Args), lager:critical(Fmt, Args)). +-define(critical(Attrs, Fmt, Args), lager:critical(Attrs, Fmt, Args)). + +-define(alert(Fmt), lager:alert(Fmt)). +-define(alert(Fmt, Args), lager:alert(Fmt, Args)). +-define(alert(Attrs, Fmt, Args), lager:alert(Attrs, Fmt, Args)). + +-define(emergency(Fmt), lager:emergency(Fmt)). +-define(emergency(Fmt, Args), lager:emergency(Fmt, Args)). +-define(emergency(Attrs, Fmt, Args), lager:emergency(Attrs, Fmt, Args)). + +-endif. diff --git a/deps/netlink/include/netlink.hrl b/deps/netlink/include/netlink.hrl new file mode 100644 index 0000000..8575420 --- /dev/null +++ b/deps/netlink/include/netlink.hrl @@ -0,0 +1,38 @@ + +-ifndef(__NETLINK_HRL__). +-define(__NETLINK_HRL__, true). + + +-record(rtnl_link_stats, { + rx_packets, %% total packets received + tx_packets, %% total packets transmitted + rx_bytes, %% total bytes received + tx_bytes, %% total bytes transmitted + rx_errors, %% bad packets received + tx_errors, %% packet transmit problems + rx_dropped, %% no space in linux buffers + tx_dropped, %% no space available in linux + multicast, %% multicast packets received + collisions, + + %% detailed rx_errors: + rx_length_errors, + rx_over_errors, %% receiver ring buff overflow + rx_crc_errors, %% recved pkt with crc error + rx_frame_errors, %% recv'd frame alignment error + rx_fifo_errors, %% recv'r fifo overrun + rx_missed_errors, %% receiver missed packet + + %% detailed tx_errors + tx_aborted_errors, + tx_carrier_errors, + tx_fifo_errors, + tx_heartbeat_errors, + tx_window_errors, + + %% for cslip etc + rx_compressed, + tx_compressed +}). + +-endif. diff --git a/deps/netlink/priv/.gitignore b/deps/netlink/priv/.gitignore new file mode 100644 index 0000000..140f8cf --- /dev/null +++ b/deps/netlink/priv/.gitignore @@ -0,0 +1 @@ +*.so diff --git a/deps/netlink/rebar.config b/deps/netlink/rebar.config new file mode 100644 index 0000000..64350f3 --- /dev/null +++ b/deps/netlink/rebar.config @@ -0,0 +1,12 @@ +%% -*- erlang -*- +%% Config file for netlink-application +{deps, [{lager, ".*", {git, "git://github.com/basho/lager.git", {tag,"3.0.2"}}}]}. +{erl_opts, [debug_info, fail_on_warning]}. + +{port_env, [ + {"CFLAGS", "$CFLAGS -DDLOG_DEFAULT=DLOG_INFO"} + ]}. + +{port_specs, [ + {"(linux)","priv/netlink_drv.so",["c_src/*.c"]} + ]}. diff --git a/deps/netlink/src/.gitignore b/deps/netlink/src/.gitignore new file mode 100644 index 0000000..b25c15b --- /dev/null +++ b/deps/netlink/src/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/deps/netlink/src/netl_codec.erl b/deps/netlink/src/netl_codec.erl new file mode 100644 index 0000000..25e4c89 --- /dev/null +++ b/deps/netlink/src/netl_codec.erl @@ -0,0 +1,2376 @@ +-module(netl_codec). +-include("netl_codec.hrl"). +-export([dec_protocol/1, enc_protocol/1]). +-export([dec_rtnetlink_rtm_protocol/1, enc_rtnetlink_rtm_protocol/1]). +-export([dec_ctm_msgtype_netlink/1, enc_ctm_msgtype_netlink/1]). +-export([dec_ctm_msgtype_ctnetlink/1, enc_ctm_msgtype_ctnetlink/1]). +-export([dec_family/1, enc_family/1]). +-export([dec_nlmsg_type/1, enc_nlmsg_type/1]). +-export([dec_ctnetlink_protoinfo_tcp_state/1, enc_ctnetlink_protoinfo_tcp_state/1]). +-export([dec_rtnetlink_rtm_type/1, enc_rtnetlink_rtm_type/1]). +-export([dec_rtnetlink_rtm_scope/1, enc_rtnetlink_rtm_scope/1]). +-export([dec_rtnetlink_rtm_table/1, enc_rtnetlink_rtm_table/1]). +-export([dec_rtnetlink_link_operstate/1, enc_rtnetlink_link_operstate/1]). +-export([dec_rtnetlink_link_linkmode/1, enc_rtnetlink_link_linkmode/1]). +-export([dec_arphrd/1, enc_arphrd/1]). +-export([dec_iff_flags/1, enc_iff_flags/1]). +-export([dec_nlm_flags/1, enc_nlm_flags/1]). +-export([dec_nlm_get_flags/1, enc_nlm_get_flags/1]). +-export([dec_nlm_new_flags/1, enc_nlm_new_flags/1]). +-export([dec_ctnetlink_status/1, enc_ctnetlink_status/1]). +-export([dec_ctnetlink_exp_flags/1, enc_ctnetlink_exp_flags/1]). +-export([dec_rtnetlink_rtm_flags/1, enc_rtnetlink_rtm_flags/1]). +-export([dec_rtnetlink_link_protinfo_flags/1, enc_rtnetlink_link_protinfo_flags/1]). +-export([dec_ifa_flags/1, enc_ifa_flags/1]). +-export([dec_ctm_msgtype_ctnetlink_exp/1, enc_ctm_msgtype_ctnetlink_exp/1]). +-export([dec_ctnetlink_tuple_proto/1, enc_ctnetlink_tuple_proto/1]). +-export([dec_ctnetlink_protoinfo/1, enc_ctnetlink_protoinfo/1]). +-export([dec_ctnetlink_exp_tuple_proto/1, enc_ctnetlink_exp_tuple_proto/1]). +-export([dec_rtnetlink_link_linkinfo/1, enc_rtnetlink_link_linkinfo/1]). +-export([dec_rtnetlink_link_protinfo/1, enc_rtnetlink_link_protinfo/1]). +-export([dec_ctnetlink/1, enc_ctnetlink/1]). +-export([dec_rtnetlink_link/1, enc_rtnetlink_link/1]). +-export([dec_ctnetlink_nat_seq_adj/1, enc_ctnetlink_nat_seq_adj/1]). +-export([dec_rtnetlink_neigh/1, enc_rtnetlink_neigh/1]). +-export([dec_rtnetlink_prefix/1, enc_rtnetlink_prefix/1]). +-export([dec_ctnetlink_tuple/1, enc_ctnetlink_tuple/1]). +-export([dec_ctnetlink_exp_tuple/1, enc_ctnetlink_exp_tuple/1]). +-export([dec_rtnetlink_route/1, enc_rtnetlink_route/1]). +-export([dec_ctnetlink_counters/1, enc_ctnetlink_counters/1]). +-export([dec_rtnetlink_route_metrics/1, enc_rtnetlink_route_metrics/1]). +-export([dec_rtnetlink_addr/1, enc_rtnetlink_addr/1]). +-export([dec_ctnetlink_tuple_ip/1, enc_ctnetlink_tuple_ip/1]). +-export([dec_ctnetlink_protoinfo_tcp/1, enc_ctnetlink_protoinfo_tcp/1]). +-export([dec_ctnetlink_help/1, enc_ctnetlink_help/1]). +-export([dec_ctnetlink_timestamp/1, enc_ctnetlink_timestamp/1]). +-export([dec_ctnetlink_exp_tuple_ip/1, enc_ctnetlink_exp_tuple_ip/1]). +-export([dec_ctnetlink_exp/1, enc_ctnetlink_exp/1]). +-export([dec_overrun/1, enc_overrun/1]). +-export([dec_newlink/1, enc_newlink/1]). +-export([dec_dellink/1, enc_dellink/1]). +-export([dec_getlink/1, enc_getlink/1]). +-export([dec_newneigh/1, enc_newneigh/1]). +-export([dec_delneigh/1, enc_delneigh/1]). +-export([dec_getneigh/1, enc_getneigh/1]). +-export([dec_ifaddrmsg/1, enc_ifaddrmsg/1]). +-export([dec_ifinfomsg/1, enc_ifinfomsg/1]). +-export([dec_rtmsg/1, enc_rtmsg/1]). +-export([dec_ndmsg/1, enc_ndmsg/1]). +-export([dec_newroute/1, enc_newroute/1]). +-export([dec_delroute/1, enc_delroute/1]). +-export([dec_getroute/1, enc_getroute/1]). +-export([dec_done/1, enc_done/1]). +-export([dec_nlmsghdr/1, enc_nlmsghdr/1]). +-export([dec_newaddr/1, enc_newaddr/1]). +-export([dec_deladdr/1, enc_deladdr/1]). +-export([dec_getaddr/1, enc_getaddr/1]). +-export([dec_error/1, enc_error/1]). +-export([dec_if_map/1, enc_if_map/1]). +-export([dec_noop/1, enc_noop/1]). +dec_protocol(0) -> ip; +dec_protocol(1) -> icmp; +dec_protocol(2) -> igmp; +dec_protocol(4) -> ipip; +dec_protocol(6) -> tcp; +dec_protocol(8) -> egp; +dec_protocol(12) -> pup; +dec_protocol(17) -> udp; +dec_protocol(22) -> idp; +dec_protocol(29) -> tp; +dec_protocol(33) -> dccp; +dec_protocol(41) -> ipv6; +dec_protocol(43) -> routing; +dec_protocol(44) -> fragment; +dec_protocol(46) -> rsvp; +dec_protocol(47) -> gre; +dec_protocol(50) -> esp; +dec_protocol(51) -> ah; +dec_protocol(58) -> icmpv6; +dec_protocol(59) -> none; +dec_protocol(60) -> dstopts; +dec_protocol(92) -> mtp; +dec_protocol(98) -> encap; +dec_protocol(103) -> pim; +dec_protocol(108) -> comp; +dec_protocol(132) -> sctp; +dec_protocol(136) -> udplite; +dec_protocol(255) -> raw; +dec_protocol(V) -> V. +enc_protocol(ip) -> 0; +enc_protocol(icmp) -> 1; +enc_protocol(igmp) -> 2; +enc_protocol(ipip) -> 4; +enc_protocol(tcp) -> 6; +enc_protocol(egp) -> 8; +enc_protocol(pup) -> 12; +enc_protocol(udp) -> 17; +enc_protocol(idp) -> 22; +enc_protocol(tp) -> 29; +enc_protocol(dccp) -> 33; +enc_protocol(ipv6) -> 41; +enc_protocol(routing) -> 43; +enc_protocol(fragment) -> 44; +enc_protocol(rsvp) -> 46; +enc_protocol(gre) -> 47; +enc_protocol(esp) -> 50; +enc_protocol(ah) -> 51; +enc_protocol(icmpv6) -> 58; +enc_protocol(none) -> 59; +enc_protocol(dstopts) -> 60; +enc_protocol(mtp) -> 92; +enc_protocol(encap) -> 98; +enc_protocol(pim) -> 103; +enc_protocol(comp) -> 108; +enc_protocol(sctp) -> 132; +enc_protocol(udplite) -> 136; +enc_protocol(raw) -> 255; +enc_protocol(V) when is_integer(V) -> V; +enc_protocol(E) -> erlang:error({undefined,E}). +dec_rtnetlink_rtm_protocol(0) -> unspec; +dec_rtnetlink_rtm_protocol(1) -> redirect; +dec_rtnetlink_rtm_protocol(2) -> kernel; +dec_rtnetlink_rtm_protocol(3) -> boot; +dec_rtnetlink_rtm_protocol(4) -> static; +dec_rtnetlink_rtm_protocol(8) -> gated; +dec_rtnetlink_rtm_protocol(9) -> ra; +dec_rtnetlink_rtm_protocol(10) -> mrt; +dec_rtnetlink_rtm_protocol(11) -> zebra; +dec_rtnetlink_rtm_protocol(12) -> bird; +dec_rtnetlink_rtm_protocol(13) -> dnrouted; +dec_rtnetlink_rtm_protocol(14) -> xorp; +dec_rtnetlink_rtm_protocol(15) -> ntk; +dec_rtnetlink_rtm_protocol(16) -> dhcp; +dec_rtnetlink_rtm_protocol(V) -> V. +enc_rtnetlink_rtm_protocol(unspec) -> 0; +enc_rtnetlink_rtm_protocol(redirect) -> 1; +enc_rtnetlink_rtm_protocol(kernel) -> 2; +enc_rtnetlink_rtm_protocol(boot) -> 3; +enc_rtnetlink_rtm_protocol(static) -> 4; +enc_rtnetlink_rtm_protocol(gated) -> 8; +enc_rtnetlink_rtm_protocol(ra) -> 9; +enc_rtnetlink_rtm_protocol(mrt) -> 10; +enc_rtnetlink_rtm_protocol(zebra) -> 11; +enc_rtnetlink_rtm_protocol(bird) -> 12; +enc_rtnetlink_rtm_protocol(dnrouted) -> 13; +enc_rtnetlink_rtm_protocol(xorp) -> 14; +enc_rtnetlink_rtm_protocol(ntk) -> 15; +enc_rtnetlink_rtm_protocol(dhcp) -> 16; +enc_rtnetlink_rtm_protocol(V) when is_integer(V) -> V; +enc_rtnetlink_rtm_protocol(E) -> erlang:error({undefined,E}). +dec_ctm_msgtype_netlink(1) -> noop; +dec_ctm_msgtype_netlink(2) -> error; +dec_ctm_msgtype_netlink(3) -> done; +dec_ctm_msgtype_netlink(4) -> overrun; +dec_ctm_msgtype_netlink(V) -> V. +enc_ctm_msgtype_netlink(noop) -> 1; +enc_ctm_msgtype_netlink(error) -> 2; +enc_ctm_msgtype_netlink(done) -> 3; +enc_ctm_msgtype_netlink(overrun) -> 4; +enc_ctm_msgtype_netlink(V) when is_integer(V) -> V; +enc_ctm_msgtype_netlink(E) -> erlang:error({undefined,E}). +dec_ctm_msgtype_ctnetlink(0) -> new; +dec_ctm_msgtype_ctnetlink(1) -> get; +dec_ctm_msgtype_ctnetlink(2) -> delete; +dec_ctm_msgtype_ctnetlink(3) -> get_ctrzero; +dec_ctm_msgtype_ctnetlink(V) -> V. +enc_ctm_msgtype_ctnetlink(new) -> 0; +enc_ctm_msgtype_ctnetlink(get) -> 1; +enc_ctm_msgtype_ctnetlink(delete) -> 2; +enc_ctm_msgtype_ctnetlink(get_ctrzero) -> 3; +enc_ctm_msgtype_ctnetlink(V) when is_integer(V) -> V; +enc_ctm_msgtype_ctnetlink(E) -> erlang:error({undefined,E}). +dec_family(0) -> unspec; +dec_family(1) -> local; +dec_family(2) -> inet; +dec_family(3) -> ax25; +dec_family(4) -> ipx; +dec_family(5) -> appletalk; +dec_family(6) -> netrom; +dec_family(7) -> bridge; +dec_family(8) -> atmpvc; +dec_family(9) -> x25; +dec_family(10) -> inet6; +dec_family(11) -> rose; +dec_family(12) -> decnet; +dec_family(13) -> netbeui; +dec_family(14) -> security; +dec_family(15) -> key; +dec_family(16) -> netlink; +dec_family(17) -> packet; +dec_family(18) -> ash; +dec_family(19) -> econet; +dec_family(20) -> atmsvc; +dec_family(21) -> rds; +dec_family(22) -> sna; +dec_family(23) -> irda; +dec_family(24) -> pppox; +dec_family(25) -> wanpipe; +dec_family(26) -> llc; +dec_family(29) -> can; +dec_family(30) -> tipc; +dec_family(31) -> bluetooth; +dec_family(32) -> iucv; +dec_family(33) -> rxrpc; +dec_family(34) -> isdn; +dec_family(35) -> phonet; +dec_family(36) -> ieee802154; +dec_family(V) -> V. +enc_family(unspec) -> 0; +enc_family(local) -> 1; +enc_family(inet) -> 2; +enc_family(ax25) -> 3; +enc_family(ipx) -> 4; +enc_family(appletalk) -> 5; +enc_family(netrom) -> 6; +enc_family(bridge) -> 7; +enc_family(atmpvc) -> 8; +enc_family(x25) -> 9; +enc_family(inet6) -> 10; +enc_family(rose) -> 11; +enc_family(decnet) -> 12; +enc_family(netbeui) -> 13; +enc_family(security) -> 14; +enc_family(key) -> 15; +enc_family(netlink) -> 16; +enc_family(packet) -> 17; +enc_family(ash) -> 18; +enc_family(econet) -> 19; +enc_family(atmsvc) -> 20; +enc_family(rds) -> 21; +enc_family(sna) -> 22; +enc_family(irda) -> 23; +enc_family(pppox) -> 24; +enc_family(wanpipe) -> 25; +enc_family(llc) -> 26; +enc_family(can) -> 29; +enc_family(tipc) -> 30; +enc_family(bluetooth) -> 31; +enc_family(iucv) -> 32; +enc_family(rxrpc) -> 33; +enc_family(isdn) -> 34; +enc_family(phonet) -> 35; +enc_family(ieee802154) -> 36; +enc_family(V) when is_integer(V) -> V; +enc_family(E) -> erlang:error({undefined,E}). +dec_nlmsg_type(1) -> noop; +dec_nlmsg_type(2) -> error; +dec_nlmsg_type(3) -> done; +dec_nlmsg_type(4) -> overrun; +dec_nlmsg_type(16) -> newlink; +dec_nlmsg_type(17) -> dellink; +dec_nlmsg_type(18) -> getlink; +dec_nlmsg_type(19) -> setlink; +dec_nlmsg_type(20) -> newaddr; +dec_nlmsg_type(21) -> deladdr; +dec_nlmsg_type(22) -> getaddr; +dec_nlmsg_type(24) -> newroute; +dec_nlmsg_type(25) -> delroute; +dec_nlmsg_type(26) -> getroute; +dec_nlmsg_type(28) -> newneigh; +dec_nlmsg_type(29) -> delneigh; +dec_nlmsg_type(30) -> getneigh; +dec_nlmsg_type(32) -> newrule; +dec_nlmsg_type(33) -> delrule; +dec_nlmsg_type(34) -> getrule; +dec_nlmsg_type(36) -> newqdisc; +dec_nlmsg_type(37) -> delqdisc; +dec_nlmsg_type(38) -> getqdisc; +dec_nlmsg_type(40) -> newtclass; +dec_nlmsg_type(41) -> deltclass; +dec_nlmsg_type(42) -> gettclass; +dec_nlmsg_type(44) -> newtfilter; +dec_nlmsg_type(45) -> deltfilter; +dec_nlmsg_type(46) -> gettfilter; +dec_nlmsg_type(48) -> newaction; +dec_nlmsg_type(49) -> delaction; +dec_nlmsg_type(50) -> getaction; +dec_nlmsg_type(52) -> newprefix; +dec_nlmsg_type(58) -> getmulticast; +dec_nlmsg_type(62) -> getanycast; +dec_nlmsg_type(64) -> newneightbl; +dec_nlmsg_type(66) -> getneightbl; +dec_nlmsg_type(67) -> setneightbl; +dec_nlmsg_type(68) -> newnduseropt; +dec_nlmsg_type(72) -> newaddrlabel; +dec_nlmsg_type(73) -> deladdrlabel; +dec_nlmsg_type(74) -> getaddrlabel; +dec_nlmsg_type(78) -> getdcb; +dec_nlmsg_type(79) -> setdcb; +dec_nlmsg_type(V) -> V. +enc_nlmsg_type(noop) -> 1; +enc_nlmsg_type(error) -> 2; +enc_nlmsg_type(done) -> 3; +enc_nlmsg_type(overrun) -> 4; +enc_nlmsg_type(newlink) -> 16; +enc_nlmsg_type(dellink) -> 17; +enc_nlmsg_type(getlink) -> 18; +enc_nlmsg_type(setlink) -> 19; +enc_nlmsg_type(newaddr) -> 20; +enc_nlmsg_type(deladdr) -> 21; +enc_nlmsg_type(getaddr) -> 22; +enc_nlmsg_type(newroute) -> 24; +enc_nlmsg_type(delroute) -> 25; +enc_nlmsg_type(getroute) -> 26; +enc_nlmsg_type(newneigh) -> 28; +enc_nlmsg_type(delneigh) -> 29; +enc_nlmsg_type(getneigh) -> 30; +enc_nlmsg_type(newrule) -> 32; +enc_nlmsg_type(delrule) -> 33; +enc_nlmsg_type(getrule) -> 34; +enc_nlmsg_type(newqdisc) -> 36; +enc_nlmsg_type(delqdisc) -> 37; +enc_nlmsg_type(getqdisc) -> 38; +enc_nlmsg_type(newtclass) -> 40; +enc_nlmsg_type(deltclass) -> 41; +enc_nlmsg_type(gettclass) -> 42; +enc_nlmsg_type(newtfilter) -> 44; +enc_nlmsg_type(deltfilter) -> 45; +enc_nlmsg_type(gettfilter) -> 46; +enc_nlmsg_type(newaction) -> 48; +enc_nlmsg_type(delaction) -> 49; +enc_nlmsg_type(getaction) -> 50; +enc_nlmsg_type(newprefix) -> 52; +enc_nlmsg_type(getmulticast) -> 58; +enc_nlmsg_type(getanycast) -> 62; +enc_nlmsg_type(newneightbl) -> 64; +enc_nlmsg_type(getneightbl) -> 66; +enc_nlmsg_type(setneightbl) -> 67; +enc_nlmsg_type(newnduseropt) -> 68; +enc_nlmsg_type(newaddrlabel) -> 72; +enc_nlmsg_type(deladdrlabel) -> 73; +enc_nlmsg_type(getaddrlabel) -> 74; +enc_nlmsg_type(getdcb) -> 78; +enc_nlmsg_type(setdcb) -> 79; +enc_nlmsg_type(V) when is_integer(V) -> V; +enc_nlmsg_type(E) -> erlang:error({undefined,E}). +dec_ctnetlink_protoinfo_tcp_state(0) -> none; +dec_ctnetlink_protoinfo_tcp_state(1) -> syn_sent; +dec_ctnetlink_protoinfo_tcp_state(2) -> syn_recv; +dec_ctnetlink_protoinfo_tcp_state(3) -> established; +dec_ctnetlink_protoinfo_tcp_state(4) -> fin_wait; +dec_ctnetlink_protoinfo_tcp_state(5) -> close_wait; +dec_ctnetlink_protoinfo_tcp_state(6) -> last_ack; +dec_ctnetlink_protoinfo_tcp_state(7) -> time_wait; +dec_ctnetlink_protoinfo_tcp_state(8) -> close; +dec_ctnetlink_protoinfo_tcp_state(9) -> listen; +dec_ctnetlink_protoinfo_tcp_state(10) -> max; +dec_ctnetlink_protoinfo_tcp_state(11) -> ignore; +dec_ctnetlink_protoinfo_tcp_state(V) -> V. +enc_ctnetlink_protoinfo_tcp_state(none) -> 0; +enc_ctnetlink_protoinfo_tcp_state(syn_sent) -> 1; +enc_ctnetlink_protoinfo_tcp_state(syn_recv) -> 2; +enc_ctnetlink_protoinfo_tcp_state(established) -> 3; +enc_ctnetlink_protoinfo_tcp_state(fin_wait) -> 4; +enc_ctnetlink_protoinfo_tcp_state(close_wait) -> 5; +enc_ctnetlink_protoinfo_tcp_state(last_ack) -> 6; +enc_ctnetlink_protoinfo_tcp_state(time_wait) -> 7; +enc_ctnetlink_protoinfo_tcp_state(close) -> 8; +enc_ctnetlink_protoinfo_tcp_state(listen) -> 9; +enc_ctnetlink_protoinfo_tcp_state(max) -> 10; +enc_ctnetlink_protoinfo_tcp_state(ignore) -> 11; +enc_ctnetlink_protoinfo_tcp_state(V) when is_integer(V) -> V; +enc_ctnetlink_protoinfo_tcp_state(E) -> erlang:error({undefined,E}). +dec_rtnetlink_rtm_type(0) -> unspec; +dec_rtnetlink_rtm_type(1) -> unicast; +dec_rtnetlink_rtm_type(2) -> local; +dec_rtnetlink_rtm_type(3) -> broadcast; +dec_rtnetlink_rtm_type(4) -> anycast; +dec_rtnetlink_rtm_type(5) -> multicast; +dec_rtnetlink_rtm_type(6) -> blackhole; +dec_rtnetlink_rtm_type(7) -> unreachable; +dec_rtnetlink_rtm_type(8) -> prohibit; +dec_rtnetlink_rtm_type(9) -> throw; +dec_rtnetlink_rtm_type(10) -> nat; +dec_rtnetlink_rtm_type(11) -> xresolve; +dec_rtnetlink_rtm_type(V) -> V. +enc_rtnetlink_rtm_type(unspec) -> 0; +enc_rtnetlink_rtm_type(unicast) -> 1; +enc_rtnetlink_rtm_type(local) -> 2; +enc_rtnetlink_rtm_type(broadcast) -> 3; +enc_rtnetlink_rtm_type(anycast) -> 4; +enc_rtnetlink_rtm_type(multicast) -> 5; +enc_rtnetlink_rtm_type(blackhole) -> 6; +enc_rtnetlink_rtm_type(unreachable) -> 7; +enc_rtnetlink_rtm_type(prohibit) -> 8; +enc_rtnetlink_rtm_type(throw) -> 9; +enc_rtnetlink_rtm_type(nat) -> 10; +enc_rtnetlink_rtm_type(xresolve) -> 11; +enc_rtnetlink_rtm_type(V) when is_integer(V) -> V; +enc_rtnetlink_rtm_type(E) -> erlang:error({undefined,E}). +dec_rtnetlink_rtm_scope(0) -> universe; +dec_rtnetlink_rtm_scope(200) -> site; +dec_rtnetlink_rtm_scope(253) -> link; +dec_rtnetlink_rtm_scope(254) -> host; +dec_rtnetlink_rtm_scope(255) -> nowhere; +dec_rtnetlink_rtm_scope(V) -> V. +enc_rtnetlink_rtm_scope(universe) -> 0; +enc_rtnetlink_rtm_scope(site) -> 200; +enc_rtnetlink_rtm_scope(link) -> 253; +enc_rtnetlink_rtm_scope(host) -> 254; +enc_rtnetlink_rtm_scope(nowhere) -> 255; +enc_rtnetlink_rtm_scope(V) when is_integer(V) -> V; +enc_rtnetlink_rtm_scope(E) -> erlang:error({undefined,E}). +dec_rtnetlink_rtm_table(0) -> unspec; +dec_rtnetlink_rtm_table(252) -> compat; +dec_rtnetlink_rtm_table(253) -> default; +dec_rtnetlink_rtm_table(254) -> main; +dec_rtnetlink_rtm_table(255) -> local; +dec_rtnetlink_rtm_table(V) -> V. +enc_rtnetlink_rtm_table(unspec) -> 0; +enc_rtnetlink_rtm_table(compat) -> 252; +enc_rtnetlink_rtm_table(default) -> 253; +enc_rtnetlink_rtm_table(main) -> 254; +enc_rtnetlink_rtm_table(local) -> 255; +enc_rtnetlink_rtm_table(V) when is_integer(V) -> V; +enc_rtnetlink_rtm_table(E) -> erlang:error({undefined,E}). +dec_rtnetlink_link_operstate(0) -> unknown; +dec_rtnetlink_link_operstate(1) -> notpresent; +dec_rtnetlink_link_operstate(2) -> down; +dec_rtnetlink_link_operstate(3) -> lowerlayerdown; +dec_rtnetlink_link_operstate(4) -> testing; +dec_rtnetlink_link_operstate(5) -> dormant; +dec_rtnetlink_link_operstate(6) -> up; +dec_rtnetlink_link_operstate(V) -> V. +enc_rtnetlink_link_operstate(unknown) -> 0; +enc_rtnetlink_link_operstate(notpresent) -> 1; +enc_rtnetlink_link_operstate(down) -> 2; +enc_rtnetlink_link_operstate(lowerlayerdown) -> 3; +enc_rtnetlink_link_operstate(testing) -> 4; +enc_rtnetlink_link_operstate(dormant) -> 5; +enc_rtnetlink_link_operstate(up) -> 6; +enc_rtnetlink_link_operstate(V) when is_integer(V) -> V; +enc_rtnetlink_link_operstate(E) -> erlang:error({undefined,E}). +dec_rtnetlink_link_linkmode(0) -> default; +dec_rtnetlink_link_linkmode(1) -> dormant; +dec_rtnetlink_link_linkmode(V) -> V. +enc_rtnetlink_link_linkmode(default) -> 0; +enc_rtnetlink_link_linkmode(dormant) -> 1; +enc_rtnetlink_link_linkmode(V) when is_integer(V) -> V; +enc_rtnetlink_link_linkmode(E) -> erlang:error({undefined,E}). +dec_arphrd(0) -> netrom; +dec_arphrd(1) -> ether; +dec_arphrd(2) -> eether; +dec_arphrd(3) -> ax25; +dec_arphrd(4) -> pronet; +dec_arphrd(5) -> chaos; +dec_arphrd(6) -> ieee802; +dec_arphrd(7) -> arcnet; +dec_arphrd(8) -> appletlk; +dec_arphrd(15) -> dlci; +dec_arphrd(19) -> atm; +dec_arphrd(23) -> metricom; +dec_arphrd(24) -> ieee1394; +dec_arphrd(27) -> eui64; +dec_arphrd(32) -> infiniband; +dec_arphrd(256) -> slip; +dec_arphrd(257) -> cslip; +dec_arphrd(258) -> slip6; +dec_arphrd(259) -> cslip6; +dec_arphrd(260) -> rsrvd; +dec_arphrd(264) -> adapt; +dec_arphrd(270) -> rose; +dec_arphrd(271) -> x25; +dec_arphrd(272) -> hwx25; +dec_arphrd(280) -> can; +dec_arphrd(512) -> ppp; +dec_arphrd(513) -> hdlc; +dec_arphrd(516) -> lapb; +dec_arphrd(517) -> ddcmp; +dec_arphrd(518) -> rawhdlc; +dec_arphrd(768) -> tunnel; +dec_arphrd(769) -> tunnel6; +dec_arphrd(770) -> frad; +dec_arphrd(771) -> skip; +dec_arphrd(772) -> loopback; +dec_arphrd(773) -> localtlk; +dec_arphrd(774) -> fddi; +dec_arphrd(775) -> bif; +dec_arphrd(776) -> sit; +dec_arphrd(777) -> ipddp; +dec_arphrd(778) -> ipgre; +dec_arphrd(779) -> pimreg; +dec_arphrd(780) -> hippi; +dec_arphrd(781) -> ash; +dec_arphrd(782) -> econet; +dec_arphrd(783) -> irda; +dec_arphrd(784) -> fcpp; +dec_arphrd(785) -> fcal; +dec_arphrd(786) -> fcpl; +dec_arphrd(787) -> fcfabric; +dec_arphrd(800) -> ieee802_tr; +dec_arphrd(801) -> ieee80211; +dec_arphrd(802) -> ieee80211_prism; +dec_arphrd(803) -> ieee80211_radiotap; +dec_arphrd(804) -> ieee802154; +dec_arphrd(820) -> phonet; +dec_arphrd(821) -> phonet_pipe; +dec_arphrd(822) -> caif; +dec_arphrd(65535) -> void; +dec_arphrd(65534) -> none; +dec_arphrd(V) -> V. +enc_arphrd(netrom) -> 0; +enc_arphrd(ether) -> 1; +enc_arphrd(eether) -> 2; +enc_arphrd(ax25) -> 3; +enc_arphrd(pronet) -> 4; +enc_arphrd(chaos) -> 5; +enc_arphrd(ieee802) -> 6; +enc_arphrd(arcnet) -> 7; +enc_arphrd(appletlk) -> 8; +enc_arphrd(dlci) -> 15; +enc_arphrd(atm) -> 19; +enc_arphrd(metricom) -> 23; +enc_arphrd(ieee1394) -> 24; +enc_arphrd(eui64) -> 27; +enc_arphrd(infiniband) -> 32; +enc_arphrd(slip) -> 256; +enc_arphrd(cslip) -> 257; +enc_arphrd(slip6) -> 258; +enc_arphrd(cslip6) -> 259; +enc_arphrd(rsrvd) -> 260; +enc_arphrd(adapt) -> 264; +enc_arphrd(rose) -> 270; +enc_arphrd(x25) -> 271; +enc_arphrd(hwx25) -> 272; +enc_arphrd(can) -> 280; +enc_arphrd(ppp) -> 512; +enc_arphrd(hdlc) -> 513; +enc_arphrd(lapb) -> 516; +enc_arphrd(ddcmp) -> 517; +enc_arphrd(rawhdlc) -> 518; +enc_arphrd(tunnel) -> 768; +enc_arphrd(tunnel6) -> 769; +enc_arphrd(frad) -> 770; +enc_arphrd(skip) -> 771; +enc_arphrd(loopback) -> 772; +enc_arphrd(localtlk) -> 773; +enc_arphrd(fddi) -> 774; +enc_arphrd(bif) -> 775; +enc_arphrd(sit) -> 776; +enc_arphrd(ipddp) -> 777; +enc_arphrd(ipgre) -> 778; +enc_arphrd(pimreg) -> 779; +enc_arphrd(hippi) -> 780; +enc_arphrd(ash) -> 781; +enc_arphrd(econet) -> 782; +enc_arphrd(irda) -> 783; +enc_arphrd(fcpp) -> 784; +enc_arphrd(fcal) -> 785; +enc_arphrd(fcpl) -> 786; +enc_arphrd(fcfabric) -> 787; +enc_arphrd(ieee802_tr) -> 800; +enc_arphrd(ieee80211) -> 801; +enc_arphrd(ieee80211_prism) -> 802; +enc_arphrd(ieee80211_radiotap) -> 803; +enc_arphrd(ieee802154) -> 804; +enc_arphrd(phonet) -> 820; +enc_arphrd(phonet_pipe) -> 821; +enc_arphrd(caif) -> 822; +enc_arphrd(void) -> 65535; +enc_arphrd(none) -> 65534; +enc_arphrd(V) when is_integer(V) -> V; +enc_arphrd(E) -> erlang:error({undefined,E}). +dec_iff_flags(0) -> up; +dec_iff_flags(1) -> broadcast; +dec_iff_flags(2) -> debug; +dec_iff_flags(3) -> loopback; +dec_iff_flags(4) -> pointopoint; +dec_iff_flags(5) -> notrailers; +dec_iff_flags(6) -> running; +dec_iff_flags(7) -> noarp; +dec_iff_flags(8) -> promisc; +dec_iff_flags(9) -> allmulti; +dec_iff_flags(10) -> master; +dec_iff_flags(11) -> slave; +dec_iff_flags(12) -> multicast; +dec_iff_flags(13) -> portsel; +dec_iff_flags(14) -> automedia; +dec_iff_flags(15) -> ynamic; +dec_iff_flags(16) -> lower_up; +dec_iff_flags(17) -> dormant; +dec_iff_flags(18) -> echo; +dec_iff_flags(V) -> V. +enc_iff_flags(up) -> 0; +enc_iff_flags(broadcast) -> 1; +enc_iff_flags(debug) -> 2; +enc_iff_flags(loopback) -> 3; +enc_iff_flags(pointopoint) -> 4; +enc_iff_flags(notrailers) -> 5; +enc_iff_flags(running) -> 6; +enc_iff_flags(noarp) -> 7; +enc_iff_flags(promisc) -> 8; +enc_iff_flags(allmulti) -> 9; +enc_iff_flags(master) -> 10; +enc_iff_flags(slave) -> 11; +enc_iff_flags(multicast) -> 12; +enc_iff_flags(portsel) -> 13; +enc_iff_flags(automedia) -> 14; +enc_iff_flags(ynamic) -> 15; +enc_iff_flags(lower_up) -> 16; +enc_iff_flags(dormant) -> 17; +enc_iff_flags(echo) -> 18; +enc_iff_flags(V) when is_integer(V) -> V; +enc_iff_flags(E) -> erlang:error({undefined,E}). +dec_nlm_flags(0) -> request; +dec_nlm_flags(1) -> multi; +dec_nlm_flags(2) -> ack; +dec_nlm_flags(3) -> echo; +dec_nlm_flags(V) -> V. +enc_nlm_flags(request) -> 0; +enc_nlm_flags(multi) -> 1; +enc_nlm_flags(ack) -> 2; +enc_nlm_flags(echo) -> 3; +enc_nlm_flags(V) when is_integer(V) -> V; +enc_nlm_flags(E) -> erlang:error({undefined,E}). +dec_nlm_get_flags(0) -> request; +dec_nlm_get_flags(1) -> multi; +dec_nlm_get_flags(2) -> ack; +dec_nlm_get_flags(3) -> echo; +dec_nlm_get_flags(8) -> root; +dec_nlm_get_flags(9) -> match; +dec_nlm_get_flags(10) -> atomic; +dec_nlm_get_flags(V) -> V. +enc_nlm_get_flags(request) -> 0; +enc_nlm_get_flags(multi) -> 1; +enc_nlm_get_flags(ack) -> 2; +enc_nlm_get_flags(echo) -> 3; +enc_nlm_get_flags(root) -> 8; +enc_nlm_get_flags(match) -> 9; +enc_nlm_get_flags(atomic) -> 10; +enc_nlm_get_flags(V) when is_integer(V) -> V; +enc_nlm_get_flags(E) -> erlang:error({undefined,E}). +dec_nlm_new_flags(0) -> request; +dec_nlm_new_flags(1) -> multi; +dec_nlm_new_flags(2) -> ack; +dec_nlm_new_flags(3) -> echo; +dec_nlm_new_flags(8) -> replace; +dec_nlm_new_flags(9) -> excl; +dec_nlm_new_flags(10) -> create; +dec_nlm_new_flags(11) -> append; +dec_nlm_new_flags(V) -> V. +enc_nlm_new_flags(request) -> 0; +enc_nlm_new_flags(multi) -> 1; +enc_nlm_new_flags(ack) -> 2; +enc_nlm_new_flags(echo) -> 3; +enc_nlm_new_flags(replace) -> 8; +enc_nlm_new_flags(excl) -> 9; +enc_nlm_new_flags(create) -> 10; +enc_nlm_new_flags(append) -> 11; +enc_nlm_new_flags(V) when is_integer(V) -> V; +enc_nlm_new_flags(E) -> erlang:error({undefined,E}). +dec_ctnetlink_status(0) -> expected; +dec_ctnetlink_status(1) -> seen_reply; +dec_ctnetlink_status(2) -> assured; +dec_ctnetlink_status(3) -> confirmed; +dec_ctnetlink_status(4) -> src_nat; +dec_ctnetlink_status(5) -> dst_nat; +dec_ctnetlink_status(6) -> seq_adjust; +dec_ctnetlink_status(7) -> src_nat_done; +dec_ctnetlink_status(8) -> dst_nat_done; +dec_ctnetlink_status(9) -> dying; +dec_ctnetlink_status(10) -> fixed_timeout; +dec_ctnetlink_status(V) -> V. +enc_ctnetlink_status(expected) -> 0; +enc_ctnetlink_status(seen_reply) -> 1; +enc_ctnetlink_status(assured) -> 2; +enc_ctnetlink_status(confirmed) -> 3; +enc_ctnetlink_status(src_nat) -> 4; +enc_ctnetlink_status(dst_nat) -> 5; +enc_ctnetlink_status(seq_adjust) -> 6; +enc_ctnetlink_status(src_nat_done) -> 7; +enc_ctnetlink_status(dst_nat_done) -> 8; +enc_ctnetlink_status(dying) -> 9; +enc_ctnetlink_status(fixed_timeout) -> 10; +enc_ctnetlink_status(V) when is_integer(V) -> V; +enc_ctnetlink_status(E) -> erlang:error({undefined,E}). +dec_ctnetlink_exp_flags(0) -> permanent; +dec_ctnetlink_exp_flags(1) -> inactive; +dec_ctnetlink_exp_flags(2) -> userspace; +dec_ctnetlink_exp_flags(V) -> V. +enc_ctnetlink_exp_flags(permanent) -> 0; +enc_ctnetlink_exp_flags(inactive) -> 1; +enc_ctnetlink_exp_flags(userspace) -> 2; +enc_ctnetlink_exp_flags(V) when is_integer(V) -> V; +enc_ctnetlink_exp_flags(E) -> erlang:error({undefined,E}). +dec_rtnetlink_rtm_flags(256) -> notify; +dec_rtnetlink_rtm_flags(512) -> cloned; +dec_rtnetlink_rtm_flags(1024) -> equalize; +dec_rtnetlink_rtm_flags(2048) -> prefix; +dec_rtnetlink_rtm_flags(V) -> V. +enc_rtnetlink_rtm_flags(notify) -> 256; +enc_rtnetlink_rtm_flags(cloned) -> 512; +enc_rtnetlink_rtm_flags(equalize) -> 1024; +enc_rtnetlink_rtm_flags(prefix) -> 2048; +enc_rtnetlink_rtm_flags(V) when is_integer(V) -> V; +enc_rtnetlink_rtm_flags(E) -> erlang:error({undefined,E}). +dec_rtnetlink_link_protinfo_flags(4) -> rs_sent; +dec_rtnetlink_link_protinfo_flags(5) -> ra_rcvd; +dec_rtnetlink_link_protinfo_flags(6) -> ra_managed; +dec_rtnetlink_link_protinfo_flags(7) -> ra_othercon; +dec_rtnetlink_link_protinfo_flags(31) -> ready; +dec_rtnetlink_link_protinfo_flags(V) -> V. +enc_rtnetlink_link_protinfo_flags(rs_sent) -> 4; +enc_rtnetlink_link_protinfo_flags(ra_rcvd) -> 5; +enc_rtnetlink_link_protinfo_flags(ra_managed) -> 6; +enc_rtnetlink_link_protinfo_flags(ra_othercon) -> 7; +enc_rtnetlink_link_protinfo_flags(ready) -> 31; +enc_rtnetlink_link_protinfo_flags(V) when is_integer(V) -> V; +enc_rtnetlink_link_protinfo_flags(E) -> erlang:error({undefined,E}). +dec_ifa_flags(0) -> secondary; +dec_ifa_flags(1) -> nodad; +dec_ifa_flags(2) -> optimistic; +dec_ifa_flags(3) -> dadfailed; +dec_ifa_flags(4) -> homeaddress; +dec_ifa_flags(5) -> deprecated; +dec_ifa_flags(6) -> tentative; +dec_ifa_flags(7) -> permanent; +dec_ifa_flags(V) -> V. +enc_ifa_flags(secondary) -> 0; +enc_ifa_flags(nodad) -> 1; +enc_ifa_flags(optimistic) -> 2; +enc_ifa_flags(dadfailed) -> 3; +enc_ifa_flags(homeaddress) -> 4; +enc_ifa_flags(deprecated) -> 5; +enc_ifa_flags(tentative) -> 6; +enc_ifa_flags(permanent) -> 7; +enc_ifa_flags(V) when is_integer(V) -> V; +enc_ifa_flags(E) -> erlang:error({undefined,E}). +dec_ctm_msgtype_ctnetlink_exp(0) -> new; +dec_ctm_msgtype_ctnetlink_exp(1) -> get; +dec_ctm_msgtype_ctnetlink_exp(2) -> delete; +dec_ctm_msgtype_ctnetlink_exp(V) -> V. +enc_ctm_msgtype_ctnetlink_exp(new) -> 0; +enc_ctm_msgtype_ctnetlink_exp(get) -> 1; +enc_ctm_msgtype_ctnetlink_exp(delete) -> 2; +enc_ctm_msgtype_ctnetlink_exp(V) when is_integer(V) -> V; +enc_ctm_msgtype_ctnetlink_exp(E) -> erlang:error({undefined,E}). +dec_ctnetlink_tuple_proto({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_tuple_proto({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_tuple_proto({1,native,<<Xe:8/unsigned-native>>}) -> + {num,dec_protocol(Xe)}; +dec_ctnetlink_tuple_proto({1,big,<<Xe:8/unsigned-big>>}) -> + {num,dec_protocol(Xe)}; +dec_ctnetlink_tuple_proto({2,native,<<X:16/unsigned-native>>}) -> + {src_port,X}; +dec_ctnetlink_tuple_proto({2,big,<<X:16/unsigned-big>>}) -> + {src_port,X}; +dec_ctnetlink_tuple_proto({3,native,<<X:16/unsigned-native>>}) -> + {dst_port,X}; +dec_ctnetlink_tuple_proto({3,big,<<X:16/unsigned-big>>}) -> + {dst_port,X}; +dec_ctnetlink_tuple_proto({4,native,<<X:16/unsigned-native>>}) -> + {icmp_id,X}; +dec_ctnetlink_tuple_proto({4,big,<<X:16/unsigned-big>>}) -> + {icmp_id,X}; +dec_ctnetlink_tuple_proto({5,native,<<X:8/unsigned-native>>}) -> + {icmp_type,X}; +dec_ctnetlink_tuple_proto({5,big,<<X:8/unsigned-big>>}) -> + {icmp_type,X}; +dec_ctnetlink_tuple_proto({6,native,<<X:8/unsigned-native>>}) -> + {icmp_code,X}; +dec_ctnetlink_tuple_proto({6,big,<<X:8/unsigned-big>>}) -> + {icmp_code,X}; +dec_ctnetlink_tuple_proto({7,native,<<X/binary>>}) -> + {icmpv6_id,X}; +dec_ctnetlink_tuple_proto({7,big,<<X/binary>>}) -> + {icmpv6_id,X}; +dec_ctnetlink_tuple_proto({8,native,<<X/binary>>}) -> + {icmpv6_type,X}; +dec_ctnetlink_tuple_proto({8,big,<<X/binary>>}) -> + {icmpv6_type,X}; +dec_ctnetlink_tuple_proto({9,native,<<X/binary>>}) -> + {icmpv6_code,X}; +dec_ctnetlink_tuple_proto({9,big,<<X/binary>>}) -> + {icmpv6_code,X}; +dec_ctnetlink_tuple_proto({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_tuple_proto({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_tuple_proto({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_tuple_proto({num,native,X}) -> + {1,native,<<(enc_protocol(X)):8/unsigned-native>>}; +enc_ctnetlink_tuple_proto({num,big,X}) -> + {1,big,<<(enc_protocol(X)):8/unsigned-big>>}; +enc_ctnetlink_tuple_proto({src_port,native,X}) -> + {2,native,<<X:16/unsigned-native>>}; +enc_ctnetlink_tuple_proto({src_port,big,X}) -> + {2,big,<<X:16/unsigned-big>>}; +enc_ctnetlink_tuple_proto({dst_port,native,X}) -> + {3,native,<<X:16/unsigned-native>>}; +enc_ctnetlink_tuple_proto({dst_port,big,X}) -> + {3,big,<<X:16/unsigned-big>>}; +enc_ctnetlink_tuple_proto({icmp_id,native,X}) -> + {4,native,<<X:16/unsigned-native>>}; +enc_ctnetlink_tuple_proto({icmp_id,big,X}) -> + {4,big,<<X:16/unsigned-big>>}; +enc_ctnetlink_tuple_proto({icmp_type,native,X}) -> + {5,native,<<X:8/unsigned-native>>}; +enc_ctnetlink_tuple_proto({icmp_type,big,X}) -> + {5,big,<<X:8/unsigned-big>>}; +enc_ctnetlink_tuple_proto({icmp_code,native,X}) -> + {6,native,<<X:8/unsigned-native>>}; +enc_ctnetlink_tuple_proto({icmp_code,big,X}) -> + {6,big,<<X:8/unsigned-big>>}; +enc_ctnetlink_tuple_proto({icmpv6_id,native,X}) -> + {7,native,<<X>>}; +enc_ctnetlink_tuple_proto({icmpv6_id,big,X}) -> + {7,big,<<X>>}; +enc_ctnetlink_tuple_proto({icmpv6_type,native,X}) -> + {8,native,<<X>>}; +enc_ctnetlink_tuple_proto({icmpv6_type,big,X}) -> + {8,big,<<X>>}; +enc_ctnetlink_tuple_proto({icmpv6_code,native,X}) -> + {9,native,<<X>>}; +enc_ctnetlink_tuple_proto({icmpv6_code,big,X}) -> + {9,big,<<X>>}; +enc_ctnetlink_tuple_proto({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_protoinfo({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_protoinfo({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_protoinfo({1,native,<<X/binary>>}) -> + {tcp,dec_ctnetlink_protoinfo_tcp(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_protoinfo({1,big,<<X/binary>>}) -> + {tcp,dec_ctnetlink_protoinfo_tcp(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_protoinfo({2,native,<<X/binary>>}) -> + {dccp,X}; +dec_ctnetlink_protoinfo({2,big,<<X/binary>>}) -> + {dccp,X}; +dec_ctnetlink_protoinfo({3,native,<<X/binary>>}) -> + {sctp,X}; +dec_ctnetlink_protoinfo({3,big,<<X/binary>>}) -> + {sctp,X}; +dec_ctnetlink_protoinfo({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_protoinfo({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_protoinfo({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_protoinfo({tcp,native,X}) -> + {1,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_protoinfo_tcp(X)))>>}; +enc_ctnetlink_protoinfo({tcp,big,X}) -> + {1,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_protoinfo_tcp(X)))>>}; +enc_ctnetlink_protoinfo({dccp,native,X}) -> + {2,native,<<X>>}; +enc_ctnetlink_protoinfo({dccp,big,X}) -> + {2,big,<<X>>}; +enc_ctnetlink_protoinfo({sctp,native,X}) -> + {3,native,<<X>>}; +enc_ctnetlink_protoinfo({sctp,big,X}) -> + {3,big,<<X>>}; +enc_ctnetlink_protoinfo({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_exp_tuple_proto({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_exp_tuple_proto({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_exp_tuple_proto({1,native,<<Xe:8/unsigned-native>>}) -> + {num,dec_protocol(Xe)}; +dec_ctnetlink_exp_tuple_proto({1,big,<<Xe:8/unsigned-big>>}) -> + {num,dec_protocol(Xe)}; +dec_ctnetlink_exp_tuple_proto({2,native,<<X:16/unsigned-native>>}) -> + {src_port,X}; +dec_ctnetlink_exp_tuple_proto({2,big,<<X:16/unsigned-big>>}) -> + {src_port,X}; +dec_ctnetlink_exp_tuple_proto({3,native,<<X:16/unsigned-native>>}) -> + {dst_port,X}; +dec_ctnetlink_exp_tuple_proto({3,big,<<X:16/unsigned-big>>}) -> + {dst_port,X}; +dec_ctnetlink_exp_tuple_proto({4,native,<<X:16/unsigned-native>>}) -> + {icmp_id,X}; +dec_ctnetlink_exp_tuple_proto({4,big,<<X:16/unsigned-big>>}) -> + {icmp_id,X}; +dec_ctnetlink_exp_tuple_proto({5,native,<<X:8/unsigned-native>>}) -> + {icmp_type,X}; +dec_ctnetlink_exp_tuple_proto({5,big,<<X:8/unsigned-big>>}) -> + {icmp_type,X}; +dec_ctnetlink_exp_tuple_proto({6,native,<<X:8/unsigned-native>>}) -> + {icmp_code,X}; +dec_ctnetlink_exp_tuple_proto({6,big,<<X:8/unsigned-big>>}) -> + {icmp_code,X}; +dec_ctnetlink_exp_tuple_proto({7,native,<<X/binary>>}) -> + {icmpv6_id,X}; +dec_ctnetlink_exp_tuple_proto({7,big,<<X/binary>>}) -> + {icmpv6_id,X}; +dec_ctnetlink_exp_tuple_proto({8,native,<<X/binary>>}) -> + {icmpv6_type,X}; +dec_ctnetlink_exp_tuple_proto({8,big,<<X/binary>>}) -> + {icmpv6_type,X}; +dec_ctnetlink_exp_tuple_proto({9,native,<<X/binary>>}) -> + {icmpv6_code,X}; +dec_ctnetlink_exp_tuple_proto({9,big,<<X/binary>>}) -> + {icmpv6_code,X}; +dec_ctnetlink_exp_tuple_proto({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_exp_tuple_proto({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_exp_tuple_proto({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_exp_tuple_proto({num,native,X}) -> + {1,native,<<(enc_protocol(X)):8/unsigned-native>>}; +enc_ctnetlink_exp_tuple_proto({num,big,X}) -> + {1,big,<<(enc_protocol(X)):8/unsigned-big>>}; +enc_ctnetlink_exp_tuple_proto({src_port,native,X}) -> + {2,native,<<X:16/unsigned-native>>}; +enc_ctnetlink_exp_tuple_proto({src_port,big,X}) -> + {2,big,<<X:16/unsigned-big>>}; +enc_ctnetlink_exp_tuple_proto({dst_port,native,X}) -> + {3,native,<<X:16/unsigned-native>>}; +enc_ctnetlink_exp_tuple_proto({dst_port,big,X}) -> + {3,big,<<X:16/unsigned-big>>}; +enc_ctnetlink_exp_tuple_proto({icmp_id,native,X}) -> + {4,native,<<X:16/unsigned-native>>}; +enc_ctnetlink_exp_tuple_proto({icmp_id,big,X}) -> + {4,big,<<X:16/unsigned-big>>}; +enc_ctnetlink_exp_tuple_proto({icmp_type,native,X}) -> + {5,native,<<X:8/unsigned-native>>}; +enc_ctnetlink_exp_tuple_proto({icmp_type,big,X}) -> + {5,big,<<X:8/unsigned-big>>}; +enc_ctnetlink_exp_tuple_proto({icmp_code,native,X}) -> + {6,native,<<X:8/unsigned-native>>}; +enc_ctnetlink_exp_tuple_proto({icmp_code,big,X}) -> + {6,big,<<X:8/unsigned-big>>}; +enc_ctnetlink_exp_tuple_proto({icmpv6_id,native,X}) -> + {7,native,<<X>>}; +enc_ctnetlink_exp_tuple_proto({icmpv6_id,big,X}) -> + {7,big,<<X>>}; +enc_ctnetlink_exp_tuple_proto({icmpv6_type,native,X}) -> + {8,native,<<X>>}; +enc_ctnetlink_exp_tuple_proto({icmpv6_type,big,X}) -> + {8,big,<<X>>}; +enc_ctnetlink_exp_tuple_proto({icmpv6_code,native,X}) -> + {9,native,<<X>>}; +enc_ctnetlink_exp_tuple_proto({icmpv6_code,big,X}) -> + {9,big,<<X>>}; +enc_ctnetlink_exp_tuple_proto({I,Endian,X}) -> {I,Endian,X}. +dec_rtnetlink_link_linkinfo({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_link_linkinfo({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_link_linkinfo({1,native,<<X/binary>>}) -> + {kind,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_link_linkinfo({1,big,<<X/binary>>}) -> + {kind,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_link_linkinfo({2,native,<<X/binary>>}) -> + {data,X}; +dec_rtnetlink_link_linkinfo({2,big,<<X/binary>>}) -> + {data,X}; +dec_rtnetlink_link_linkinfo({3,native,<<X/binary>>}) -> + {xstats,X}; +dec_rtnetlink_link_linkinfo({3,big,<<X/binary>>}) -> + {xstats,X}; +dec_rtnetlink_link_linkinfo({I,_Endian,Bin}) -> {I,Bin}. +enc_rtnetlink_link_linkinfo({unspec,native,X}) -> + {0,native,<<X>>}; +enc_rtnetlink_link_linkinfo({unspec,big,X}) -> + {0,big,<<X>>}; +enc_rtnetlink_link_linkinfo({kind,native,X}) -> + {1,native,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_link_linkinfo({kind,big,X}) -> + {1,big,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_link_linkinfo({data,native,X}) -> + {2,native,<<X>>}; +enc_rtnetlink_link_linkinfo({data,big,X}) -> + {2,big,<<X>>}; +enc_rtnetlink_link_linkinfo({xstats,native,X}) -> + {3,native,<<X>>}; +enc_rtnetlink_link_linkinfo({xstats,big,X}) -> + {3,big,<<X>>}; +enc_rtnetlink_link_linkinfo({I,Endian,X}) -> {I,Endian,X}. +dec_rtnetlink_link_protinfo({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_link_protinfo({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_link_protinfo({1,native,<<Xf:32/unsigned-native>>}) -> + {flags,netlink_codec:decode_flags(Xf,fun dec_rtnetlink_link_protinfo_flags/1)}; +dec_rtnetlink_link_protinfo({1,big,<<Xf:32/unsigned-big>>}) -> + {flags,netlink_codec:decode_flags(Xf,fun dec_rtnetlink_link_protinfo_flags/1)}; +dec_rtnetlink_link_protinfo({2,native,<<X/binary>>}) -> + {conf,[Xi || <<Xi:32/signed-native>> <= X]}; +dec_rtnetlink_link_protinfo({2,big,<<X/binary>>}) -> + {conf,[Xi || <<Xi:32/signed-big>> <= X]}; +dec_rtnetlink_link_protinfo({3,native,<<X/binary>>}) -> + {stats,[Xi || <<Xi:64/unsigned-native>> <= X]}; +dec_rtnetlink_link_protinfo({3,big,<<X/binary>>}) -> + {stats,[Xi || <<Xi:64/unsigned-big>> <= X]}; +dec_rtnetlink_link_protinfo({4,native,<<X/binary>>}) -> + {mcast,X}; +dec_rtnetlink_link_protinfo({4,big,<<X/binary>>}) -> + {mcast,X}; +dec_rtnetlink_link_protinfo({5,native,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-native>> <= X]}; +dec_rtnetlink_link_protinfo({5,big,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-big>> <= X]}; +dec_rtnetlink_link_protinfo({6,native,<<X/binary>>}) -> + {icmp6stats,[Xi || <<Xi:64/unsigned-native>> <= X]}; +dec_rtnetlink_link_protinfo({6,big,<<X/binary>>}) -> + {icmp6stats,[Xi || <<Xi:64/unsigned-big>> <= X]}; +dec_rtnetlink_link_protinfo({I,_Endian,Bin}) -> {I,Bin}. +enc_rtnetlink_link_protinfo({unspec,native,X}) -> + {0,native,<<X>>}; +enc_rtnetlink_link_protinfo({unspec,big,X}) -> + {0,big,<<X>>}; +enc_rtnetlink_link_protinfo({flags,native,X}) -> + {1,native,<<(netlink_codec:encode_flags(X,fun enc_rtnetlink_link_protinfo_flags/1)):32/unsigned-native>>}; +enc_rtnetlink_link_protinfo({flags,big,X}) -> + {1,big,<<(netlink_codec:encode_flags(X,fun enc_rtnetlink_link_protinfo_flags/1)):32/unsigned-big>>}; +enc_rtnetlink_link_protinfo({conf,native,X}) -> + {2,native,<<(<< <<Xi:32/signed-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link_protinfo({conf,big,X}) -> + {2,big,<<(<< <<Xi:32/signed-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link_protinfo({stats,native,X}) -> + {3,native,<<(<< <<Xi:64/unsigned-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link_protinfo({stats,big,X}) -> + {3,big,<<(<< <<Xi:64/unsigned-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link_protinfo({mcast,native,X}) -> + {4,native,<<X>>}; +enc_rtnetlink_link_protinfo({mcast,big,X}) -> + {4,big,<<X>>}; +enc_rtnetlink_link_protinfo({cacheinfo,native,X}) -> + {5,native,<<(<< <<Xi:32/unsigned-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link_protinfo({cacheinfo,big,X}) -> + {5,big,<<(<< <<Xi:32/unsigned-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link_protinfo({icmp6stats,native,X}) -> + {6,native,<<(<< <<Xi:64/unsigned-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link_protinfo({icmp6stats,big,X}) -> + {6,big,<<(<< <<Xi:64/unsigned-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link_protinfo({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink({1,native,<<X/binary>>}) -> + {tuple_orig,dec_ctnetlink_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({1,big,<<X/binary>>}) -> + {tuple_orig,dec_ctnetlink_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({2,native,<<X/binary>>}) -> + {tuple_reply,dec_ctnetlink_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({2,big,<<X/binary>>}) -> + {tuple_reply,dec_ctnetlink_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({3,native,<<Xf:32/unsigned-native>>}) -> + {status,netlink_codec:decode_flags(Xf,fun dec_ctnetlink_status/1)}; +dec_ctnetlink({3,big,<<Xf:32/unsigned-big>>}) -> + {status,netlink_codec:decode_flags(Xf,fun dec_ctnetlink_status/1)}; +dec_ctnetlink({4,native,<<X/binary>>}) -> + {protoinfo,dec_ctnetlink_protoinfo(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({4,big,<<X/binary>>}) -> + {protoinfo,dec_ctnetlink_protoinfo(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({5,native,<<X/binary>>}) -> + {help,dec_ctnetlink_help(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({5,big,<<X/binary>>}) -> + {help,dec_ctnetlink_help(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({6,native,<<X/binary>>}) -> + {nat_src,X}; +dec_ctnetlink({6,big,<<X/binary>>}) -> + {nat_src,X}; +dec_ctnetlink({7,native,<<X:32/unsigned-native>>}) -> + {timeout,X}; +dec_ctnetlink({7,big,<<X:32/unsigned-big>>}) -> + {timeout,X}; +dec_ctnetlink({8,native,<<X:32/unsigned-native>>}) -> + {mark,X}; +dec_ctnetlink({8,big,<<X:32/unsigned-big>>}) -> + {mark,X}; +dec_ctnetlink({9,native,<<X/binary>>}) -> + {counters_orig,dec_ctnetlink_counters(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({9,big,<<X/binary>>}) -> + {counters_orig,dec_ctnetlink_counters(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({10,native,<<X/binary>>}) -> + {counters_reply,dec_ctnetlink_counters(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({10,big,<<X/binary>>}) -> + {counters_reply,dec_ctnetlink_counters(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({11,native,<<X:32/unsigned-native>>}) -> + {use,X}; +dec_ctnetlink({11,big,<<X:32/unsigned-big>>}) -> + {use,X}; +dec_ctnetlink({12,native,<<X:32/unsigned-native>>}) -> + {id,X}; +dec_ctnetlink({12,big,<<X:32/unsigned-big>>}) -> + {id,X}; +dec_ctnetlink({13,native,<<X/binary>>}) -> + {nat_dst,X}; +dec_ctnetlink({13,big,<<X/binary>>}) -> + {nat_dst,X}; +dec_ctnetlink({14,native,<<X/binary>>}) -> + {tuple_master,dec_ctnetlink_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({14,big,<<X/binary>>}) -> + {tuple_master,dec_ctnetlink_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({15,native,<<X/binary>>}) -> + {nat_seq_adj_orig,dec_ctnetlink_nat_seq_adj(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({15,big,<<X/binary>>}) -> + {nat_seq_adj_orig,dec_ctnetlink_nat_seq_adj(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({16,native,<<X/binary>>}) -> + {nat_seq_adj_reply,dec_ctnetlink_nat_seq_adj(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({16,big,<<X/binary>>}) -> + {nat_seq_adj_reply,dec_ctnetlink_nat_seq_adj(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({17,native,<<X:32/unsigned-native>>}) -> + {secmark,X}; +dec_ctnetlink({17,big,<<X:32/unsigned-big>>}) -> + {secmark,X}; +dec_ctnetlink({18,native,<<X:16/unsigned-native>>}) -> + {zone,X}; +dec_ctnetlink({18,big,<<X:16/unsigned-big>>}) -> + {zone,X}; +dec_ctnetlink({19,native,<<X/binary>>}) -> + {secctx,X}; +dec_ctnetlink({19,big,<<X/binary>>}) -> + {secctx,X}; +dec_ctnetlink({20,native,<<X/binary>>}) -> + {timestamp,dec_ctnetlink_timestamp(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({20,big,<<X/binary>>}) -> + {timestamp,dec_ctnetlink_timestamp(netlink_codec:decode_tlv(X))}; +dec_ctnetlink({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink({tuple_orig,native,X}) -> + {1,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple(X)))>>}; +enc_ctnetlink({tuple_orig,big,X}) -> + {1,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple(X)))>>}; +enc_ctnetlink({tuple_reply,native,X}) -> + {2,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple(X)))>>}; +enc_ctnetlink({tuple_reply,big,X}) -> + {2,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple(X)))>>}; +enc_ctnetlink({status,native,X}) -> + {3,native,<<(netlink_codec:encode_flags(X,fun enc_ctnetlink_status/1)):32/unsigned-native>>}; +enc_ctnetlink({status,big,X}) -> + {3,big,<<(netlink_codec:encode_flags(X,fun enc_ctnetlink_status/1)):32/unsigned-big>>}; +enc_ctnetlink({protoinfo,native,X}) -> + {4,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_protoinfo(X)))>>}; +enc_ctnetlink({protoinfo,big,X}) -> + {4,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_protoinfo(X)))>>}; +enc_ctnetlink({help,native,X}) -> + {5,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_help(X)))>>}; +enc_ctnetlink({help,big,X}) -> + {5,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_help(X)))>>}; +enc_ctnetlink({nat_src,native,X}) -> + {6,native,<<X>>}; +enc_ctnetlink({nat_src,big,X}) -> + {6,big,<<X>>}; +enc_ctnetlink({timeout,native,X}) -> + {7,native,<<X:32/unsigned-native>>}; +enc_ctnetlink({timeout,big,X}) -> + {7,big,<<X:32/unsigned-big>>}; +enc_ctnetlink({mark,native,X}) -> + {8,native,<<X:32/unsigned-native>>}; +enc_ctnetlink({mark,big,X}) -> + {8,big,<<X:32/unsigned-big>>}; +enc_ctnetlink({counters_orig,native,X}) -> + {9,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_counters(X)))>>}; +enc_ctnetlink({counters_orig,big,X}) -> + {9,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_counters(X)))>>}; +enc_ctnetlink({counters_reply,native,X}) -> + {10,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_counters(X)))>>}; +enc_ctnetlink({counters_reply,big,X}) -> + {10,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_counters(X)))>>}; +enc_ctnetlink({use,native,X}) -> + {11,native,<<X:32/unsigned-native>>}; +enc_ctnetlink({use,big,X}) -> + {11,big,<<X:32/unsigned-big>>}; +enc_ctnetlink({id,native,X}) -> + {12,native,<<X:32/unsigned-native>>}; +enc_ctnetlink({id,big,X}) -> + {12,big,<<X:32/unsigned-big>>}; +enc_ctnetlink({nat_dst,native,X}) -> + {13,native,<<X>>}; +enc_ctnetlink({nat_dst,big,X}) -> + {13,big,<<X>>}; +enc_ctnetlink({tuple_master,native,X}) -> + {14,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple(X)))>>}; +enc_ctnetlink({tuple_master,big,X}) -> + {14,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple(X)))>>}; +enc_ctnetlink({nat_seq_adj_orig,native,X}) -> + {15,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_nat_seq_adj(X)))>>}; +enc_ctnetlink({nat_seq_adj_orig,big,X}) -> + {15,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_nat_seq_adj(X)))>>}; +enc_ctnetlink({nat_seq_adj_reply,native,X}) -> + {16,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_nat_seq_adj(X)))>>}; +enc_ctnetlink({nat_seq_adj_reply,big,X}) -> + {16,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_nat_seq_adj(X)))>>}; +enc_ctnetlink({secmark,native,X}) -> + {17,native,<<X:32/unsigned-native>>}; +enc_ctnetlink({secmark,big,X}) -> + {17,big,<<X:32/unsigned-big>>}; +enc_ctnetlink({zone,native,X}) -> + {18,native,<<X:16/unsigned-native>>}; +enc_ctnetlink({zone,big,X}) -> + {18,big,<<X:16/unsigned-big>>}; +enc_ctnetlink({secctx,native,X}) -> + {19,native,<<X>>}; +enc_ctnetlink({secctx,big,X}) -> + {19,big,<<X>>}; +enc_ctnetlink({timestamp,native,X}) -> + {20,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_timestamp(X)))>>}; +enc_ctnetlink({timestamp,big,X}) -> + {20,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_timestamp(X)))>>}; +enc_ctnetlink({I,Endian,X}) -> {I,Endian,X}. +dec_rtnetlink_link({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_link({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_link({1,native,<<X1,X2,X3,X4,X5,X6>>}) -> + {address,{X1,X2,X3,X4,X5,X6}}; +dec_rtnetlink_link({1,big,<<X1,X2,X3,X4,X5,X6>>}) -> + {address,{X1,X2,X3,X4,X5,X6}}; +dec_rtnetlink_link({2,native,<<X1,X2,X3,X4,X5,X6>>}) -> + {broadcast,{X1,X2,X3,X4,X5,X6}}; +dec_rtnetlink_link({2,big,<<X1,X2,X3,X4,X5,X6>>}) -> + {broadcast,{X1,X2,X3,X4,X5,X6}}; +dec_rtnetlink_link({3,native,<<X/binary>>}) -> + {ifname,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_link({3,big,<<X/binary>>}) -> + {ifname,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_link({4,native,<<X:32/unsigned-native>>}) -> + {mtu,X}; +dec_rtnetlink_link({4,big,<<X:32/unsigned-big>>}) -> + {mtu,X}; +dec_rtnetlink_link({5,native,<<X:32/unsigned-native>>}) -> + {link,X}; +dec_rtnetlink_link({5,big,<<X:32/unsigned-big>>}) -> + {link,X}; +dec_rtnetlink_link({6,native,<<X/binary>>}) -> + {qdisc,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_link({6,big,<<X/binary>>}) -> + {qdisc,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_link({7,native,<<X/binary>>}) -> + {stats,[Xi || <<Xi:32/unsigned-native>> <= X]}; +dec_rtnetlink_link({7,big,<<X/binary>>}) -> + {stats,[Xi || <<Xi:32/unsigned-big>> <= X]}; +dec_rtnetlink_link({8,native,<<X/binary>>}) -> + {cost,X}; +dec_rtnetlink_link({8,big,<<X/binary>>}) -> + {cost,X}; +dec_rtnetlink_link({9,native,<<X/binary>>}) -> + {priority,X}; +dec_rtnetlink_link({9,big,<<X/binary>>}) -> + {priority,X}; +dec_rtnetlink_link({10,native,<<X/binary>>}) -> + {master,X}; +dec_rtnetlink_link({10,big,<<X/binary>>}) -> + {master,X}; +dec_rtnetlink_link({11,native,<<X/binary>>}) -> + {wireless,X}; +dec_rtnetlink_link({11,big,<<X/binary>>}) -> + {wireless,X}; +dec_rtnetlink_link({12,native,<<X/binary>>}) -> + {protinfo,[dec_rtnetlink_link_protinfo(Xi) || Xi <- netlink_codec:decode_tlv_list(X)]}; +dec_rtnetlink_link({12,big,<<X/binary>>}) -> + {protinfo,[dec_rtnetlink_link_protinfo(Xi) || Xi <- netlink_codec:decode_tlv_list(X)]}; +dec_rtnetlink_link({13,native,<<X:32/unsigned-native>>}) -> + {txqlen,X}; +dec_rtnetlink_link({13,big,<<X:32/unsigned-big>>}) -> + {txqlen,X}; +dec_rtnetlink_link({14,native,<<X1:64/unsigned-native,X2:64/unsigned-native,X3:64/unsigned-native,X4:16/unsigned-native,X5:8/unsigned-native,X6:8/unsigned-native>>}) -> + {map,#if_map{memstart=X1,memend=X2,baseaddr=X3,irq=X4,dma=X5,port=X6}}; +dec_rtnetlink_link({14,big,<<X1:64/unsigned-big,X2:64/unsigned-big,X3:64/unsigned-big,X4:16/unsigned-big,X5:8/unsigned-big,X6:8/unsigned-big>>}) -> + {map,#if_map{memstart=X1,memend=X2,baseaddr=X3,irq=X4,dma=X5,port=X6}}; +dec_rtnetlink_link({15,native,<<X/binary>>}) -> + {weight,X}; +dec_rtnetlink_link({15,big,<<X/binary>>}) -> + {weight,X}; +dec_rtnetlink_link({16,native,<<Xe:8/unsigned-native>>}) -> + {operstate,dec_rtnetlink_link_operstate(Xe)}; +dec_rtnetlink_link({16,big,<<Xe:8/unsigned-big>>}) -> + {operstate,dec_rtnetlink_link_operstate(Xe)}; +dec_rtnetlink_link({17,native,<<Xe:8/unsigned-native>>}) -> + {linkmode,dec_rtnetlink_link_linkmode(Xe)}; +dec_rtnetlink_link({17,big,<<Xe:8/unsigned-big>>}) -> + {linkmode,dec_rtnetlink_link_linkmode(Xe)}; +dec_rtnetlink_link({18,native,<<X/binary>>}) -> + {linkinfo,[dec_rtnetlink_link_linkinfo(Xi) || Xi <- netlink_codec:decode_tlv_list(X)]}; +dec_rtnetlink_link({18,big,<<X/binary>>}) -> + {linkinfo,[dec_rtnetlink_link_linkinfo(Xi) || Xi <- netlink_codec:decode_tlv_list(X)]}; +dec_rtnetlink_link({19,native,<<X/binary>>}) -> + {net_ns_pid,X}; +dec_rtnetlink_link({19,big,<<X/binary>>}) -> + {net_ns_pid,X}; +dec_rtnetlink_link({20,native,<<X/binary>>}) -> + {ifalias,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_link({20,big,<<X/binary>>}) -> + {ifalias,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_link({21,native,<<X:32/unsigned-native>>}) -> + {num_vf,X}; +dec_rtnetlink_link({21,big,<<X:32/unsigned-big>>}) -> + {num_vf,X}; +dec_rtnetlink_link({22,native,<<X/binary>>}) -> + {vfinfo_list,X}; +dec_rtnetlink_link({22,big,<<X/binary>>}) -> + {vfinfo_list,X}; +dec_rtnetlink_link({23,native,<<X/binary>>}) -> + {stats64,[Xi || <<Xi:64/unsigned-native>> <= X]}; +dec_rtnetlink_link({23,big,<<X/binary>>}) -> + {stats64,[Xi || <<Xi:64/unsigned-big>> <= X]}; +dec_rtnetlink_link({24,native,<<X/binary>>}) -> + {vf_ports,X}; +dec_rtnetlink_link({24,big,<<X/binary>>}) -> + {vf_ports,X}; +dec_rtnetlink_link({25,native,<<X/binary>>}) -> + {port_self,X}; +dec_rtnetlink_link({25,big,<<X/binary>>}) -> + {port_self,X}; +dec_rtnetlink_link({26,native,<<X/binary>>}) -> + {af_spec,X}; +dec_rtnetlink_link({26,big,<<X/binary>>}) -> + {af_spec,X}; +dec_rtnetlink_link({27,native,<<X:32/unsigned-native>>}) -> + {group,X}; +dec_rtnetlink_link({27,big,<<X:32/unsigned-big>>}) -> + {group,X}; +dec_rtnetlink_link({28,native,<<X/binary>>}) -> + {net_ns_fd,X}; +dec_rtnetlink_link({28,big,<<X/binary>>}) -> + {net_ns_fd,X}; +dec_rtnetlink_link({29,native,<<X/binary>>}) -> + {ext_mask,X}; +dec_rtnetlink_link({29,big,<<X/binary>>}) -> + {ext_mask,X}; +dec_rtnetlink_link({30,native,<<X:32/unsigned-native>>}) -> + {promiscuity,X}; +dec_rtnetlink_link({30,big,<<X:32/unsigned-big>>}) -> + {promiscuity,X}; +dec_rtnetlink_link({I,_Endian,Bin}) -> {I,Bin}. +enc_rtnetlink_link({unspec,native,X}) -> + {0,native,<<X>>}; +enc_rtnetlink_link({unspec,big,X}) -> + {0,big,<<X>>}; +enc_rtnetlink_link({address,native,{X1,X2,X3,X4,X5,X6}}) -> + {1,native,<<X1:8,X2:8,X3:8,X4:8,X5:8,X6:8>>}; +enc_rtnetlink_link({address,big,{X1,X2,X3,X4,X5,X6}}) -> + {1,big,<<X1:8,X2:8,X3:8,X4:8,X5:8,X6:8>>}; +enc_rtnetlink_link({broadcast,native,{X1,X2,X3,X4,X5,X6}}) -> + {2,native,<<X1:8,X2:8,X3:8,X4:8,X5:8,X6:8>>}; +enc_rtnetlink_link({broadcast,big,{X1,X2,X3,X4,X5,X6}}) -> + {2,big,<<X1:8,X2:8,X3:8,X4:8,X5:8,X6:8>>}; +enc_rtnetlink_link({ifname,native,X}) -> + {3,native,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_link({ifname,big,X}) -> + {3,big,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_link({mtu,native,X}) -> + {4,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_link({mtu,big,X}) -> + {4,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_link({link,native,X}) -> + {5,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_link({link,big,X}) -> + {5,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_link({qdisc,native,X}) -> + {6,native,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_link({qdisc,big,X}) -> + {6,big,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_link({stats,native,X}) -> + {7,native,<<(<< <<Xi:32/unsigned-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link({stats,big,X}) -> + {7,big,<<(<< <<Xi:32/unsigned-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link({cost,native,X}) -> + {8,native,<<X>>}; +enc_rtnetlink_link({cost,big,X}) -> + {8,big,<<X>>}; +enc_rtnetlink_link({priority,native,X}) -> + {9,native,<<X>>}; +enc_rtnetlink_link({priority,big,X}) -> + {9,big,<<X>>}; +enc_rtnetlink_link({master,native,X}) -> + {10,native,<<X>>}; +enc_rtnetlink_link({master,big,X}) -> + {10,big,<<X>>}; +enc_rtnetlink_link({wireless,native,X}) -> + {11,native,<<X>>}; +enc_rtnetlink_link({wireless,big,X}) -> + {11,big,<<X>>}; +enc_rtnetlink_link({protinfo,native,X}) -> + {12,native,<<(netlink_codec:encode_tlv_list([enc_rtnetlink_link_protinfo(Xi) || Xi <- X]))/binary>>}; +enc_rtnetlink_link({protinfo,big,X}) -> + {12,big,<<(netlink_codec:encode_tlv_list([enc_rtnetlink_link_protinfo(Xi) || Xi <- X]))/binary>>}; +enc_rtnetlink_link({txqlen,native,X}) -> + {13,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_link({txqlen,big,X}) -> + {13,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_link({map,native,#if_map{memstart=X1,memend=X2,baseaddr=X3,irq=X4,dma=X5,port=X6}}) -> + {14,native,<<X1:64/unsigned-native,X2:64/unsigned-native,X3:64/unsigned-native,X4:16/unsigned-native,X5:8/unsigned-native,X6:8/unsigned-native>>}; +enc_rtnetlink_link({map,big,#if_map{memstart=X1,memend=X2,baseaddr=X3,irq=X4,dma=X5,port=X6}}) -> + {14,big,<<X1:64/unsigned-big,X2:64/unsigned-big,X3:64/unsigned-big,X4:16/unsigned-big,X5:8/unsigned-big,X6:8/unsigned-big>>}; +enc_rtnetlink_link({weight,native,X}) -> + {15,native,<<X>>}; +enc_rtnetlink_link({weight,big,X}) -> + {15,big,<<X>>}; +enc_rtnetlink_link({operstate,native,X}) -> + {16,native,<<(enc_rtnetlink_link_operstate(X)):8/unsigned-native>>}; +enc_rtnetlink_link({operstate,big,X}) -> + {16,big,<<(enc_rtnetlink_link_operstate(X)):8/unsigned-big>>}; +enc_rtnetlink_link({linkmode,native,X}) -> + {17,native,<<(enc_rtnetlink_link_linkmode(X)):8/unsigned-native>>}; +enc_rtnetlink_link({linkmode,big,X}) -> + {17,big,<<(enc_rtnetlink_link_linkmode(X)):8/unsigned-big>>}; +enc_rtnetlink_link({linkinfo,native,X}) -> + {18,native,<<(netlink_codec:encode_tlv_list([enc_rtnetlink_link_linkinfo(Xi) || Xi <- X]))/binary>>}; +enc_rtnetlink_link({linkinfo,big,X}) -> + {18,big,<<(netlink_codec:encode_tlv_list([enc_rtnetlink_link_linkinfo(Xi) || Xi <- X]))/binary>>}; +enc_rtnetlink_link({net_ns_pid,native,X}) -> + {19,native,<<X>>}; +enc_rtnetlink_link({net_ns_pid,big,X}) -> + {19,big,<<X>>}; +enc_rtnetlink_link({ifalias,native,X}) -> + {20,native,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_link({ifalias,big,X}) -> + {20,big,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_link({num_vf,native,X}) -> + {21,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_link({num_vf,big,X}) -> + {21,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_link({vfinfo_list,native,X}) -> + {22,native,<<X>>}; +enc_rtnetlink_link({vfinfo_list,big,X}) -> + {22,big,<<X>>}; +enc_rtnetlink_link({stats64,native,X}) -> + {23,native,<<(<< <<Xi:64/unsigned-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link({stats64,big,X}) -> + {23,big,<<(<< <<Xi:64/unsigned-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_link({vf_ports,native,X}) -> + {24,native,<<X>>}; +enc_rtnetlink_link({vf_ports,big,X}) -> + {24,big,<<X>>}; +enc_rtnetlink_link({port_self,native,X}) -> + {25,native,<<X>>}; +enc_rtnetlink_link({port_self,big,X}) -> + {25,big,<<X>>}; +enc_rtnetlink_link({af_spec,native,X}) -> + {26,native,<<X>>}; +enc_rtnetlink_link({af_spec,big,X}) -> + {26,big,<<X>>}; +enc_rtnetlink_link({group,native,X}) -> + {27,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_link({group,big,X}) -> + {27,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_link({net_ns_fd,native,X}) -> + {28,native,<<X>>}; +enc_rtnetlink_link({net_ns_fd,big,X}) -> + {28,big,<<X>>}; +enc_rtnetlink_link({ext_mask,native,X}) -> + {29,native,<<X>>}; +enc_rtnetlink_link({ext_mask,big,X}) -> + {29,big,<<X>>}; +enc_rtnetlink_link({promiscuity,native,X}) -> + {30,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_link({promiscuity,big,X}) -> + {30,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_link({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_nat_seq_adj({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_nat_seq_adj({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_nat_seq_adj({1,native,<<X:32/unsigned-native>>}) -> + {correction_pos,X}; +dec_ctnetlink_nat_seq_adj({1,big,<<X:32/unsigned-big>>}) -> + {correction_pos,X}; +dec_ctnetlink_nat_seq_adj({2,native,<<X:32/unsigned-native>>}) -> + {offset_before,X}; +dec_ctnetlink_nat_seq_adj({2,big,<<X:32/unsigned-big>>}) -> + {offset_before,X}; +dec_ctnetlink_nat_seq_adj({3,native,<<X:32/unsigned-native>>}) -> + {offset_after,X}; +dec_ctnetlink_nat_seq_adj({3,big,<<X:32/unsigned-big>>}) -> + {offset_after,X}; +dec_ctnetlink_nat_seq_adj({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_nat_seq_adj({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_nat_seq_adj({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_nat_seq_adj({correction_pos,native,X}) -> + {1,native,<<X:32/unsigned-native>>}; +enc_ctnetlink_nat_seq_adj({correction_pos,big,X}) -> + {1,big,<<X:32/unsigned-big>>}; +enc_ctnetlink_nat_seq_adj({offset_before,native,X}) -> + {2,native,<<X:32/unsigned-native>>}; +enc_ctnetlink_nat_seq_adj({offset_before,big,X}) -> + {2,big,<<X:32/unsigned-big>>}; +enc_ctnetlink_nat_seq_adj({offset_after,native,X}) -> + {3,native,<<X:32/unsigned-native>>}; +enc_ctnetlink_nat_seq_adj({offset_after,big,X}) -> + {3,big,<<X:32/unsigned-big>>}; +enc_ctnetlink_nat_seq_adj({I,Endian,X}) -> {I,Endian,X}. +dec_rtnetlink_neigh({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_neigh({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_neigh({1,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {dst,{X1,X2,X3,X4}}; +dec_rtnetlink_neigh({1,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {dst,{X1,X2,X3,X4}}; +dec_rtnetlink_neigh({1,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {dst,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_neigh({1,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {dst,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_neigh({2,native,<<X1,X2,X3,X4,X5,X6>>}) -> + {lladdr,{X1,X2,X3,X4,X5,X6}}; +dec_rtnetlink_neigh({2,big,<<X1,X2,X3,X4,X5,X6>>}) -> + {lladdr,{X1,X2,X3,X4,X5,X6}}; +dec_rtnetlink_neigh({3,native,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-native>> <= X]}; +dec_rtnetlink_neigh({3,big,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-big>> <= X]}; +dec_rtnetlink_neigh({4,native,<<X:32/unsigned-native>>}) -> + {probes,X}; +dec_rtnetlink_neigh({4,big,<<X:32/unsigned-big>>}) -> + {probes,X}; +dec_rtnetlink_neigh({I,_Endian,Bin}) -> {I,Bin}. +enc_rtnetlink_neigh({unspec,native,X}) -> + {0,native,<<X>>}; +enc_rtnetlink_neigh({unspec,big,X}) -> + {0,big,<<X>>}; +enc_rtnetlink_neigh({dst,native,{X1,X2,X3,X4}}) -> + {1,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_neigh({dst,big,{X1,X2,X3,X4}}) -> + {1,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_neigh({dst,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {1,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_neigh({dst,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {1,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_neigh({lladdr,native,{X1,X2,X3,X4,X5,X6}}) -> + {2,native,<<X1:8,X2:8,X3:8,X4:8,X5:8,X6:8>>}; +enc_rtnetlink_neigh({lladdr,big,{X1,X2,X3,X4,X5,X6}}) -> + {2,big,<<X1:8,X2:8,X3:8,X4:8,X5:8,X6:8>>}; +enc_rtnetlink_neigh({cacheinfo,native,X}) -> + {3,native,<<(<< <<Xi:32/unsigned-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_neigh({cacheinfo,big,X}) -> + {3,big,<<(<< <<Xi:32/unsigned-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_neigh({probes,native,X}) -> + {4,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_neigh({probes,big,X}) -> + {4,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_neigh({I,Endian,X}) -> {I,Endian,X}. +dec_rtnetlink_prefix({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_prefix({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_prefix({1,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {address,{X1,X2,X3,X4}}; +dec_rtnetlink_prefix({1,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {address,{X1,X2,X3,X4}}; +dec_rtnetlink_prefix({1,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {address,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_prefix({1,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {address,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_prefix({2,native,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-native>> <= X]}; +dec_rtnetlink_prefix({2,big,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-big>> <= X]}; +dec_rtnetlink_prefix({I,_Endian,Bin}) -> {I,Bin}. +enc_rtnetlink_prefix({unspec,native,X}) -> + {0,native,<<X>>}; +enc_rtnetlink_prefix({unspec,big,X}) -> + {0,big,<<X>>}; +enc_rtnetlink_prefix({address,native,{X1,X2,X3,X4}}) -> + {1,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_prefix({address,big,{X1,X2,X3,X4}}) -> + {1,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_prefix({address,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {1,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_prefix({address,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {1,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_prefix({cacheinfo,native,X}) -> + {2,native,<<(<< <<Xi:32/unsigned-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_prefix({cacheinfo,big,X}) -> + {2,big,<<(<< <<Xi:32/unsigned-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_prefix({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_tuple({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_tuple({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_tuple({1,native,<<X/binary>>}) -> + {ip,dec_ctnetlink_tuple_ip(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_tuple({1,big,<<X/binary>>}) -> + {ip,dec_ctnetlink_tuple_ip(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_tuple({2,native,<<X/binary>>}) -> + {proto,dec_ctnetlink_tuple_proto(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_tuple({2,big,<<X/binary>>}) -> + {proto,dec_ctnetlink_tuple_proto(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_tuple({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_tuple({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_tuple({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_tuple({ip,native,X}) -> + {1,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple_ip(X)))>>}; +enc_ctnetlink_tuple({ip,big,X}) -> + {1,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple_ip(X)))>>}; +enc_ctnetlink_tuple({proto,native,X}) -> + {2,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple_proto(X)))>>}; +enc_ctnetlink_tuple({proto,big,X}) -> + {2,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_tuple_proto(X)))>>}; +enc_ctnetlink_tuple({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_exp_tuple({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_exp_tuple({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_exp_tuple({1,native,<<X/binary>>}) -> + {ip,dec_ctnetlink_exp_tuple_ip(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp_tuple({1,big,<<X/binary>>}) -> + {ip,dec_ctnetlink_exp_tuple_ip(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp_tuple({2,native,<<X/binary>>}) -> + {proto,dec_ctnetlink_exp_tuple_proto(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp_tuple({2,big,<<X/binary>>}) -> + {proto,dec_ctnetlink_exp_tuple_proto(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp_tuple({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_exp_tuple({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_exp_tuple({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_exp_tuple({ip,native,X}) -> + {1,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple_ip(X)))>>}; +enc_ctnetlink_exp_tuple({ip,big,X}) -> + {1,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple_ip(X)))>>}; +enc_ctnetlink_exp_tuple({proto,native,X}) -> + {2,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple_proto(X)))>>}; +enc_ctnetlink_exp_tuple({proto,big,X}) -> + {2,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple_proto(X)))>>}; +enc_ctnetlink_exp_tuple({I,Endian,X}) -> {I,Endian,X}. +dec_rtnetlink_route({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_route({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_route({1,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {dst,{X1,X2,X3,X4}}; +dec_rtnetlink_route({1,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {dst,{X1,X2,X3,X4}}; +dec_rtnetlink_route({1,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {dst,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_route({1,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {dst,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_route({2,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {src,{X1,X2,X3,X4}}; +dec_rtnetlink_route({2,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {src,{X1,X2,X3,X4}}; +dec_rtnetlink_route({2,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {src,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_route({2,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {src,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_route({3,native,<<X:32/unsigned-native>>}) -> + {iif,X}; +dec_rtnetlink_route({3,big,<<X:32/unsigned-big>>}) -> + {iif,X}; +dec_rtnetlink_route({4,native,<<X:32/unsigned-native>>}) -> + {oif,X}; +dec_rtnetlink_route({4,big,<<X:32/unsigned-big>>}) -> + {oif,X}; +dec_rtnetlink_route({5,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {gateway,{X1,X2,X3,X4}}; +dec_rtnetlink_route({5,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {gateway,{X1,X2,X3,X4}}; +dec_rtnetlink_route({5,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {gateway,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_route({5,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {gateway,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_route({6,native,<<X:32/unsigned-native>>}) -> + {priority,X}; +dec_rtnetlink_route({6,big,<<X:32/unsigned-big>>}) -> + {priority,X}; +dec_rtnetlink_route({7,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {prefsrc,{X1,X2,X3,X4}}; +dec_rtnetlink_route({7,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {prefsrc,{X1,X2,X3,X4}}; +dec_rtnetlink_route({7,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {prefsrc,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_route({7,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {prefsrc,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_route({8,native,<<X/binary>>}) -> + {metrics,[dec_rtnetlink_route_metrics(Xi) || Xi <- netlink_codec:decode_tlv_list(X)]}; +dec_rtnetlink_route({8,big,<<X/binary>>}) -> + {metrics,[dec_rtnetlink_route_metrics(Xi) || Xi <- netlink_codec:decode_tlv_list(X)]}; +dec_rtnetlink_route({9,native,<<X/binary>>}) -> + {multipath,X}; +dec_rtnetlink_route({9,big,<<X/binary>>}) -> + {multipath,X}; +dec_rtnetlink_route({10,native,<<X/binary>>}) -> + {protoinfo,X}; +dec_rtnetlink_route({10,big,<<X/binary>>}) -> + {protoinfo,X}; +dec_rtnetlink_route({11,native,<<X:32/unsigned-native>>}) -> + {flow,X}; +dec_rtnetlink_route({11,big,<<X:32/unsigned-big>>}) -> + {flow,X}; +dec_rtnetlink_route({12,native,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-native>> <= X]}; +dec_rtnetlink_route({12,big,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-big>> <= X]}; +dec_rtnetlink_route({13,native,<<X/binary>>}) -> + {session,X}; +dec_rtnetlink_route({13,big,<<X/binary>>}) -> + {session,X}; +dec_rtnetlink_route({14,native,<<X/binary>>}) -> + {mp_algo,X}; +dec_rtnetlink_route({14,big,<<X/binary>>}) -> + {mp_algo,X}; +dec_rtnetlink_route({15,native,<<X:32/unsigned-native>>}) -> + {table,X}; +dec_rtnetlink_route({15,big,<<X:32/unsigned-big>>}) -> + {table,X}; +dec_rtnetlink_route({I,_Endian,Bin}) -> {I,Bin}. +enc_rtnetlink_route({unspec,native,X}) -> + {0,native,<<X>>}; +enc_rtnetlink_route({unspec,big,X}) -> + {0,big,<<X>>}; +enc_rtnetlink_route({dst,native,{X1,X2,X3,X4}}) -> + {1,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_route({dst,big,{X1,X2,X3,X4}}) -> + {1,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_route({dst,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {1,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_route({dst,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {1,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_route({src,native,{X1,X2,X3,X4}}) -> + {2,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_route({src,big,{X1,X2,X3,X4}}) -> + {2,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_route({src,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {2,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_route({src,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {2,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_route({iif,native,X}) -> + {3,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route({iif,big,X}) -> + {3,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route({oif,native,X}) -> + {4,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route({oif,big,X}) -> + {4,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route({gateway,native,{X1,X2,X3,X4}}) -> + {5,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_route({gateway,big,{X1,X2,X3,X4}}) -> + {5,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_route({gateway,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {5,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_route({gateway,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {5,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_route({priority,native,X}) -> + {6,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route({priority,big,X}) -> + {6,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route({prefsrc,native,{X1,X2,X3,X4}}) -> + {7,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_route({prefsrc,big,{X1,X2,X3,X4}}) -> + {7,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_route({prefsrc,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {7,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_route({prefsrc,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {7,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_route({metrics,native,X}) -> + {8,native,<<(netlink_codec:encode_tlv_list([enc_rtnetlink_route_metrics(Xi) || Xi <- X]))/binary>>}; +enc_rtnetlink_route({metrics,big,X}) -> + {8,big,<<(netlink_codec:encode_tlv_list([enc_rtnetlink_route_metrics(Xi) || Xi <- X]))/binary>>}; +enc_rtnetlink_route({multipath,native,X}) -> + {9,native,<<X>>}; +enc_rtnetlink_route({multipath,big,X}) -> + {9,big,<<X>>}; +enc_rtnetlink_route({protoinfo,native,X}) -> + {10,native,<<X>>}; +enc_rtnetlink_route({protoinfo,big,X}) -> + {10,big,<<X>>}; +enc_rtnetlink_route({flow,native,X}) -> + {11,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route({flow,big,X}) -> + {11,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route({cacheinfo,native,X}) -> + {12,native,<<(<< <<Xi:32/unsigned-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_route({cacheinfo,big,X}) -> + {12,big,<<(<< <<Xi:32/unsigned-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_route({session,native,X}) -> + {13,native,<<X>>}; +enc_rtnetlink_route({session,big,X}) -> + {13,big,<<X>>}; +enc_rtnetlink_route({mp_algo,native,X}) -> + {14,native,<<X>>}; +enc_rtnetlink_route({mp_algo,big,X}) -> + {14,big,<<X>>}; +enc_rtnetlink_route({table,native,X}) -> + {15,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route({table,big,X}) -> + {15,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_counters({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_counters({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_counters({1,native,<<X:64/unsigned-native>>}) -> + {packets,X}; +dec_ctnetlink_counters({1,big,<<X:64/unsigned-big>>}) -> + {packets,X}; +dec_ctnetlink_counters({2,native,<<X:64/unsigned-native>>}) -> + {bytes,X}; +dec_ctnetlink_counters({2,big,<<X:64/unsigned-big>>}) -> + {bytes,X}; +dec_ctnetlink_counters({3,native,<<X:32/unsigned-native>>}) -> + {packets32,X}; +dec_ctnetlink_counters({3,big,<<X:32/unsigned-big>>}) -> + {packets32,X}; +dec_ctnetlink_counters({4,native,<<X:32/unsigned-native>>}) -> + {bytes32,X}; +dec_ctnetlink_counters({4,big,<<X:32/unsigned-big>>}) -> + {bytes32,X}; +dec_ctnetlink_counters({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_counters({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_counters({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_counters({packets,native,X}) -> + {1,native,<<X:64/unsigned-native>>}; +enc_ctnetlink_counters({packets,big,X}) -> + {1,big,<<X:64/unsigned-big>>}; +enc_ctnetlink_counters({bytes,native,X}) -> + {2,native,<<X:64/unsigned-native>>}; +enc_ctnetlink_counters({bytes,big,X}) -> + {2,big,<<X:64/unsigned-big>>}; +enc_ctnetlink_counters({packets32,native,X}) -> + {3,native,<<X:32/unsigned-native>>}; +enc_ctnetlink_counters({packets32,big,X}) -> + {3,big,<<X:32/unsigned-big>>}; +enc_ctnetlink_counters({bytes32,native,X}) -> + {4,native,<<X:32/unsigned-native>>}; +enc_ctnetlink_counters({bytes32,big,X}) -> + {4,big,<<X:32/unsigned-big>>}; +enc_ctnetlink_counters({I,Endian,X}) -> {I,Endian,X}. +dec_rtnetlink_route_metrics({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_route_metrics({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_route_metrics({1,native,<<X:32/unsigned-native>>}) -> + {lock,X}; +dec_rtnetlink_route_metrics({1,big,<<X:32/unsigned-big>>}) -> + {lock,X}; +dec_rtnetlink_route_metrics({2,native,<<X:32/unsigned-native>>}) -> + {mtu,X}; +dec_rtnetlink_route_metrics({2,big,<<X:32/unsigned-big>>}) -> + {mtu,X}; +dec_rtnetlink_route_metrics({3,native,<<X:32/unsigned-native>>}) -> + {window,X}; +dec_rtnetlink_route_metrics({3,big,<<X:32/unsigned-big>>}) -> + {window,X}; +dec_rtnetlink_route_metrics({4,native,<<X:32/unsigned-native>>}) -> + {rtt,X}; +dec_rtnetlink_route_metrics({4,big,<<X:32/unsigned-big>>}) -> + {rtt,X}; +dec_rtnetlink_route_metrics({5,native,<<X:32/unsigned-native>>}) -> + {rttvar,X}; +dec_rtnetlink_route_metrics({5,big,<<X:32/unsigned-big>>}) -> + {rttvar,X}; +dec_rtnetlink_route_metrics({6,native,<<X:32/unsigned-native>>}) -> + {ssthresh,X}; +dec_rtnetlink_route_metrics({6,big,<<X:32/unsigned-big>>}) -> + {ssthresh,X}; +dec_rtnetlink_route_metrics({7,native,<<X:32/unsigned-native>>}) -> + {cwnd,X}; +dec_rtnetlink_route_metrics({7,big,<<X:32/unsigned-big>>}) -> + {cwnd,X}; +dec_rtnetlink_route_metrics({8,native,<<X:32/unsigned-native>>}) -> + {advmss,X}; +dec_rtnetlink_route_metrics({8,big,<<X:32/unsigned-big>>}) -> + {advmss,X}; +dec_rtnetlink_route_metrics({9,native,<<X:32/unsigned-native>>}) -> + {reordering,X}; +dec_rtnetlink_route_metrics({9,big,<<X:32/unsigned-big>>}) -> + {reordering,X}; +dec_rtnetlink_route_metrics({10,native,<<X:32/unsigned-native>>}) -> + {hoplimit,X}; +dec_rtnetlink_route_metrics({10,big,<<X:32/unsigned-big>>}) -> + {hoplimit,X}; +dec_rtnetlink_route_metrics({11,native,<<X:32/unsigned-native>>}) -> + {initcwnd,X}; +dec_rtnetlink_route_metrics({11,big,<<X:32/unsigned-big>>}) -> + {initcwnd,X}; +dec_rtnetlink_route_metrics({12,native,<<X:32/unsigned-native>>}) -> + {features,X}; +dec_rtnetlink_route_metrics({12,big,<<X:32/unsigned-big>>}) -> + {features,X}; +dec_rtnetlink_route_metrics({13,native,<<X:32/unsigned-native>>}) -> + {rto_min,X}; +dec_rtnetlink_route_metrics({13,big,<<X:32/unsigned-big>>}) -> + {rto_min,X}; +dec_rtnetlink_route_metrics({14,native,<<X:32/unsigned-native>>}) -> + {initrwnd,X}; +dec_rtnetlink_route_metrics({14,big,<<X:32/unsigned-big>>}) -> + {initrwnd,X}; +dec_rtnetlink_route_metrics({I,_Endian,Bin}) -> {I,Bin}. +enc_rtnetlink_route_metrics({unspec,native,X}) -> + {0,native,<<X>>}; +enc_rtnetlink_route_metrics({unspec,big,X}) -> + {0,big,<<X>>}; +enc_rtnetlink_route_metrics({lock,native,X}) -> + {1,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({lock,big,X}) -> + {1,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({mtu,native,X}) -> + {2,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({mtu,big,X}) -> + {2,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({window,native,X}) -> + {3,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({window,big,X}) -> + {3,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({rtt,native,X}) -> + {4,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({rtt,big,X}) -> + {4,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({rttvar,native,X}) -> + {5,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({rttvar,big,X}) -> + {5,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({ssthresh,native,X}) -> + {6,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({ssthresh,big,X}) -> + {6,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({cwnd,native,X}) -> + {7,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({cwnd,big,X}) -> + {7,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({advmss,native,X}) -> + {8,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({advmss,big,X}) -> + {8,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({reordering,native,X}) -> + {9,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({reordering,big,X}) -> + {9,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({hoplimit,native,X}) -> + {10,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({hoplimit,big,X}) -> + {10,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({initcwnd,native,X}) -> + {11,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({initcwnd,big,X}) -> + {11,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({features,native,X}) -> + {12,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({features,big,X}) -> + {12,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({rto_min,native,X}) -> + {13,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({rto_min,big,X}) -> + {13,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({initrwnd,native,X}) -> + {14,native,<<X:32/unsigned-native>>}; +enc_rtnetlink_route_metrics({initrwnd,big,X}) -> + {14,big,<<X:32/unsigned-big>>}; +enc_rtnetlink_route_metrics({I,Endian,X}) -> {I,Endian,X}. +dec_rtnetlink_addr({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_addr({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_rtnetlink_addr({1,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {address,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({1,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {address,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({1,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {address,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({1,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {address,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({2,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {local,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({2,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {local,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({2,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {local,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({2,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {local,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({3,native,<<X/binary>>}) -> + {label,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_addr({3,big,<<X/binary>>}) -> + {label,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_rtnetlink_addr({4,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {broadcast,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({4,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {broadcast,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({4,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {broadcast,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({4,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {broadcast,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({5,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {anycast,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({5,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {anycast,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({5,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {anycast,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({5,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {anycast,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({6,native,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-native>> <= X]}; +dec_rtnetlink_addr({6,big,<<X/binary>>}) -> + {cacheinfo,[Xi || <<Xi:32/unsigned-big>> <= X]}; +dec_rtnetlink_addr({7,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {multicast,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({7,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {multicast,{X1,X2,X3,X4}}; +dec_rtnetlink_addr({7,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {multicast,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({7,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {multicast,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_rtnetlink_addr({I,_Endian,Bin}) -> {I,Bin}. +enc_rtnetlink_addr({unspec,native,X}) -> + {0,native,<<X>>}; +enc_rtnetlink_addr({unspec,big,X}) -> + {0,big,<<X>>}; +enc_rtnetlink_addr({address,native,{X1,X2,X3,X4}}) -> + {1,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({address,big,{X1,X2,X3,X4}}) -> + {1,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({address,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {1,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({address,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {1,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({local,native,{X1,X2,X3,X4}}) -> + {2,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({local,big,{X1,X2,X3,X4}}) -> + {2,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({local,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {2,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({local,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {2,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({label,native,X}) -> + {3,native,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_addr({label,big,X}) -> + {3,big,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_rtnetlink_addr({broadcast,native,{X1,X2,X3,X4}}) -> + {4,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({broadcast,big,{X1,X2,X3,X4}}) -> + {4,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({broadcast,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {4,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({broadcast,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {4,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({anycast,native,{X1,X2,X3,X4}}) -> + {5,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({anycast,big,{X1,X2,X3,X4}}) -> + {5,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({anycast,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {5,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({anycast,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {5,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({cacheinfo,native,X}) -> + {6,native,<<(<< <<Xi:32/unsigned-native>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_addr({cacheinfo,big,X}) -> + {6,big,<<(<< <<Xi:32/unsigned-big>> || Xi <- X>>)/binary>>}; +enc_rtnetlink_addr({multicast,native,{X1,X2,X3,X4}}) -> + {7,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({multicast,big,{X1,X2,X3,X4}}) -> + {7,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_rtnetlink_addr({multicast,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {7,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({multicast,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {7,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_rtnetlink_addr({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_tuple_ip({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_tuple_ip({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_tuple_ip({1,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {v4_src,{X1,X2,X3,X4}}; +dec_ctnetlink_tuple_ip({1,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {v4_src,{X1,X2,X3,X4}}; +dec_ctnetlink_tuple_ip({2,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {v4_dst,{X1,X2,X3,X4}}; +dec_ctnetlink_tuple_ip({2,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {v4_dst,{X1,X2,X3,X4}}; +dec_ctnetlink_tuple_ip({3,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {v6_src,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_ctnetlink_tuple_ip({3,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {v6_src,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_ctnetlink_tuple_ip({4,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {v6_dst,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_ctnetlink_tuple_ip({4,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {v6_dst,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_ctnetlink_tuple_ip({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_tuple_ip({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_tuple_ip({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_tuple_ip({v4_src,native,{X1,X2,X3,X4}}) -> + {1,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_ctnetlink_tuple_ip({v4_src,big,{X1,X2,X3,X4}}) -> + {1,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_ctnetlink_tuple_ip({v4_dst,native,{X1,X2,X3,X4}}) -> + {2,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_ctnetlink_tuple_ip({v4_dst,big,{X1,X2,X3,X4}}) -> + {2,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_ctnetlink_tuple_ip({v6_src,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {3,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_ctnetlink_tuple_ip({v6_src,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {3,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_ctnetlink_tuple_ip({v6_dst,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {4,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_ctnetlink_tuple_ip({v6_dst,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {4,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_ctnetlink_tuple_ip({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_protoinfo_tcp({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_protoinfo_tcp({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_protoinfo_tcp({1,native,<<Xe:8/unsigned-native>>}) -> + {state,dec_ctnetlink_protoinfo_tcp_state(Xe)}; +dec_ctnetlink_protoinfo_tcp({1,big,<<Xe:8/unsigned-big>>}) -> + {state,dec_ctnetlink_protoinfo_tcp_state(Xe)}; +dec_ctnetlink_protoinfo_tcp({2,native,<<X:8/unsigned-native>>}) -> + {wscale_original,X}; +dec_ctnetlink_protoinfo_tcp({2,big,<<X:8/unsigned-big>>}) -> + {wscale_original,X}; +dec_ctnetlink_protoinfo_tcp({3,native,<<X:8/unsigned-native>>}) -> + {wscale_reply,X}; +dec_ctnetlink_protoinfo_tcp({3,big,<<X:8/unsigned-big>>}) -> + {wscale_reply,X}; +dec_ctnetlink_protoinfo_tcp({4,native,<<X:16/unsigned-native>>}) -> + {flags_original,X}; +dec_ctnetlink_protoinfo_tcp({4,big,<<X:16/unsigned-big>>}) -> + {flags_original,X}; +dec_ctnetlink_protoinfo_tcp({5,native,<<X:16/unsigned-native>>}) -> + {flags_reply,X}; +dec_ctnetlink_protoinfo_tcp({5,big,<<X:16/unsigned-big>>}) -> + {flags_reply,X}; +dec_ctnetlink_protoinfo_tcp({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_protoinfo_tcp({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_protoinfo_tcp({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_protoinfo_tcp({state,native,X}) -> + {1,native,<<(enc_ctnetlink_protoinfo_tcp_state(X)):8/unsigned-native>>}; +enc_ctnetlink_protoinfo_tcp({state,big,X}) -> + {1,big,<<(enc_ctnetlink_protoinfo_tcp_state(X)):8/unsigned-big>>}; +enc_ctnetlink_protoinfo_tcp({wscale_original,native,X}) -> + {2,native,<<X:8/unsigned-native>>}; +enc_ctnetlink_protoinfo_tcp({wscale_original,big,X}) -> + {2,big,<<X:8/unsigned-big>>}; +enc_ctnetlink_protoinfo_tcp({wscale_reply,native,X}) -> + {3,native,<<X:8/unsigned-native>>}; +enc_ctnetlink_protoinfo_tcp({wscale_reply,big,X}) -> + {3,big,<<X:8/unsigned-big>>}; +enc_ctnetlink_protoinfo_tcp({flags_original,native,X}) -> + {4,native,<<X:16/unsigned-native>>}; +enc_ctnetlink_protoinfo_tcp({flags_original,big,X}) -> + {4,big,<<X:16/unsigned-big>>}; +enc_ctnetlink_protoinfo_tcp({flags_reply,native,X}) -> + {5,native,<<X:16/unsigned-native>>}; +enc_ctnetlink_protoinfo_tcp({flags_reply,big,X}) -> + {5,big,<<X:16/unsigned-big>>}; +enc_ctnetlink_protoinfo_tcp({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_help({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_help({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_help({1,native,<<X/binary>>}) -> + {name,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_ctnetlink_help({1,big,<<X/binary>>}) -> + {name,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_ctnetlink_help({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_help({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_help({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_help({name,native,X}) -> + {1,native,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_ctnetlink_help({name,big,X}) -> + {1,big,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_ctnetlink_help({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_timestamp({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_timestamp({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_timestamp({1,native,<<X:64/unsigned-native>>}) -> + {start,X}; +dec_ctnetlink_timestamp({1,big,<<X:64/unsigned-big>>}) -> + {start,X}; +dec_ctnetlink_timestamp({2,native,<<X:64/unsigned-native>>}) -> + {stop,X}; +dec_ctnetlink_timestamp({2,big,<<X:64/unsigned-big>>}) -> + {stop,X}; +dec_ctnetlink_timestamp({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_timestamp({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_timestamp({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_timestamp({start,native,X}) -> + {1,native,<<X:64/unsigned-native>>}; +enc_ctnetlink_timestamp({start,big,X}) -> + {1,big,<<X:64/unsigned-big>>}; +enc_ctnetlink_timestamp({stop,native,X}) -> + {2,native,<<X:64/unsigned-native>>}; +enc_ctnetlink_timestamp({stop,big,X}) -> + {2,big,<<X:64/unsigned-big>>}; +enc_ctnetlink_timestamp({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_exp_tuple_ip({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_exp_tuple_ip({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_exp_tuple_ip({1,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {v4_src,{X1,X2,X3,X4}}; +dec_ctnetlink_exp_tuple_ip({1,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {v4_src,{X1,X2,X3,X4}}; +dec_ctnetlink_exp_tuple_ip({2,native,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {v4_dst,{X1,X2,X3,X4}}; +dec_ctnetlink_exp_tuple_ip({2,big,<<X1:8,X2:8,X3:8,X4:8>>}) -> + {v4_dst,{X1,X2,X3,X4}}; +dec_ctnetlink_exp_tuple_ip({3,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {v6_src,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_ctnetlink_exp_tuple_ip({3,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {v6_src,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_ctnetlink_exp_tuple_ip({4,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {v6_dst,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_ctnetlink_exp_tuple_ip({4,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}) -> + {v6_dst,{X1,X2,X3,X4,X5,X6,X7,X8}}; +dec_ctnetlink_exp_tuple_ip({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_exp_tuple_ip({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_exp_tuple_ip({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_exp_tuple_ip({v4_src,native,{X1,X2,X3,X4}}) -> + {1,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_ctnetlink_exp_tuple_ip({v4_src,big,{X1,X2,X3,X4}}) -> + {1,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_ctnetlink_exp_tuple_ip({v4_dst,native,{X1,X2,X3,X4}}) -> + {2,native,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_ctnetlink_exp_tuple_ip({v4_dst,big,{X1,X2,X3,X4}}) -> + {2,big,<<X1:8,X2:8,X3:8,X4:8>>}; +enc_ctnetlink_exp_tuple_ip({v6_src,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {3,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_ctnetlink_exp_tuple_ip({v6_src,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {3,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_ctnetlink_exp_tuple_ip({v6_dst,native,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {4,native,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_ctnetlink_exp_tuple_ip({v6_dst,big,{X1,X2,X3,X4,X5,X6,X7,X8}}) -> + {4,big,<<X1:16,X2:16,X3:16,X4:16,X5:16,X6:16,X7:16,X8:16>>}; +enc_ctnetlink_exp_tuple_ip({I,Endian,X}) -> {I,Endian,X}. +dec_ctnetlink_exp({0,native,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_exp({0,big,<<X/binary>>}) -> + {unspec,X}; +dec_ctnetlink_exp({1,native,<<X/binary>>}) -> + {master,dec_ctnetlink_exp_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp({1,big,<<X/binary>>}) -> + {master,dec_ctnetlink_exp_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp({2,native,<<X/binary>>}) -> + {tuple,dec_ctnetlink_exp_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp({2,big,<<X/binary>>}) -> + {tuple,dec_ctnetlink_exp_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp({3,native,<<X/binary>>}) -> + {mask,dec_ctnetlink_exp_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp({3,big,<<X/binary>>}) -> + {mask,dec_ctnetlink_exp_tuple(netlink_codec:decode_tlv(X))}; +dec_ctnetlink_exp({4,native,<<X:32/unsigned-native>>}) -> + {timeout,X}; +dec_ctnetlink_exp({4,big,<<X:32/unsigned-big>>}) -> + {timeout,X}; +dec_ctnetlink_exp({5,native,<<X:32/unsigned-native>>}) -> + {id,X}; +dec_ctnetlink_exp({5,big,<<X:32/unsigned-big>>}) -> + {id,X}; +dec_ctnetlink_exp({6,native,<<X/binary>>}) -> + {help_name,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_ctnetlink_exp({6,big,<<X/binary>>}) -> + {help_name,binary_to_list(hd(binary:split(X,<<0>>)))}; +dec_ctnetlink_exp({7,native,<<X:16/unsigned-native>>}) -> + {zone,X}; +dec_ctnetlink_exp({7,big,<<X:16/unsigned-big>>}) -> + {zone,X}; +dec_ctnetlink_exp({8,native,<<Xf:32/unsigned-native>>}) -> + {flags,netlink_codec:decode_flags(Xf,fun dec_ctnetlink_exp_flags/1)}; +dec_ctnetlink_exp({8,big,<<Xf:32/unsigned-big>>}) -> + {flags,netlink_codec:decode_flags(Xf,fun dec_ctnetlink_exp_flags/1)}; +dec_ctnetlink_exp({I,_Endian,Bin}) -> {I,Bin}. +enc_ctnetlink_exp({unspec,native,X}) -> + {0,native,<<X>>}; +enc_ctnetlink_exp({unspec,big,X}) -> + {0,big,<<X>>}; +enc_ctnetlink_exp({master,native,X}) -> + {1,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple(X)))>>}; +enc_ctnetlink_exp({master,big,X}) -> + {1,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple(X)))>>}; +enc_ctnetlink_exp({tuple,native,X}) -> + {2,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple(X)))>>}; +enc_ctnetlink_exp({tuple,big,X}) -> + {2,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple(X)))>>}; +enc_ctnetlink_exp({mask,native,X}) -> + {3,native,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple(X)))>>}; +enc_ctnetlink_exp({mask,big,X}) -> + {3,big,<<(netlink_codec:encode_tlv(enc_ctnetlink_exp_tuple(X)))>>}; +enc_ctnetlink_exp({timeout,native,X}) -> + {4,native,<<X:32/unsigned-native>>}; +enc_ctnetlink_exp({timeout,big,X}) -> + {4,big,<<X:32/unsigned-big>>}; +enc_ctnetlink_exp({id,native,X}) -> + {5,native,<<X:32/unsigned-native>>}; +enc_ctnetlink_exp({id,big,X}) -> + {5,big,<<X:32/unsigned-big>>}; +enc_ctnetlink_exp({help_name,native,X}) -> + {6,native,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_ctnetlink_exp({help_name,big,X}) -> + {6,big,<<(erlang:iolist_to_binary([X,0]))/binary>>}; +enc_ctnetlink_exp({zone,native,X}) -> + {7,native,<<X:16/unsigned-native>>}; +enc_ctnetlink_exp({zone,big,X}) -> + {7,big,<<X:16/unsigned-big>>}; +enc_ctnetlink_exp({flags,native,X}) -> + {8,native,<<(netlink_codec:encode_flags(X,fun enc_ctnetlink_exp_flags/1)):32/unsigned-native>>}; +enc_ctnetlink_exp({flags,big,X}) -> + {8,big,<<(netlink_codec:encode_flags(X,fun enc_ctnetlink_exp_flags/1)):32/unsigned-big>>}; +enc_ctnetlink_exp({I,Endian,X}) -> {I,Endian,X}. +dec_overrun({native,<<X1:32/unsigned-native>>}) -> + #overrun{status=X1}. +enc_overrun({_Endian,#overrun{status=X1}}) -> <<X1:32/unsigned-native>>. +dec_newlink({native,<<X1e:8/unsigned-native,_:8/unsigned-native,X3e:16/unsigned-native,X4:32/signed-native,X5f:32/unsigned-native,X6f:32/unsigned-native,X7/binary>>}) -> + #newlink{family=dec_family(X1e),arphrd=dec_arphrd(X3e),index=X4,flags=netlink_codec:decode_flags(X5f,fun dec_iff_flags/1),change=netlink_codec:decode_flags(X6f,fun dec_iff_flags/1),attributes=[dec_rtnetlink_link(X7i) || X7i <- netlink_codec:decode_tlv_list(X7)]}. +enc_newlink({_Endian,#newlink{family=X1,arphrd=X3,index=X4,flags=X5,change=X6,attributes=X7}}) -> <<(enc_family(X1)):8/unsigned-native,0:8/unsigned-native,(enc_arphrd(X3)):16/unsigned-native,X4:32/signed-native,(netlink_codec:encode_flags(X5,fun enc_iff_flags/1)):32/unsigned-native,(netlink_codec:encode_flags(X6,fun enc_iff_flags/1)):32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_link(X7i) || X7i <- X7]))/binary>>. +dec_dellink({native,<<X1e:8/unsigned-native,_:8/unsigned-native,X3e:16/unsigned-native,X4:32/signed-native,X5f:32/unsigned-native,X6f:32/unsigned-native,X7/binary>>}) -> + #dellink{family=dec_family(X1e),arphrd=dec_arphrd(X3e),index=X4,flags=netlink_codec:decode_flags(X5f,fun dec_iff_flags/1),change=netlink_codec:decode_flags(X6f,fun dec_iff_flags/1),attributes=[dec_rtnetlink_link(X7i) || X7i <- netlink_codec:decode_tlv_list(X7)]}. +enc_dellink({_Endian,#dellink{family=X1,arphrd=X3,index=X4,flags=X5,change=X6,attributes=X7}}) -> <<(enc_family(X1)):8/unsigned-native,0:8/unsigned-native,(enc_arphrd(X3)):16/unsigned-native,X4:32/signed-native,(netlink_codec:encode_flags(X5,fun enc_iff_flags/1)):32/unsigned-native,(netlink_codec:encode_flags(X6,fun enc_iff_flags/1)):32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_link(X7i) || X7i <- X7]))/binary>>. +dec_getlink({native,<<X1e:8/unsigned-native,_:8/unsigned-native,X3e:16/unsigned-native,X4:32/signed-native,X5f:32/unsigned-native,X6f:32/unsigned-native,X7/binary>>}) -> + #getlink{family=dec_family(X1e),arphrd=dec_arphrd(X3e),index=X4,flags=netlink_codec:decode_flags(X5f,fun dec_iff_flags/1),change=netlink_codec:decode_flags(X6f,fun dec_iff_flags/1),attributes=[dec_rtnetlink_link(X7i) || X7i <- netlink_codec:decode_tlv_list(X7)]}. +enc_getlink({_Endian,#getlink{family=X1,arphrd=X3,index=X4,flags=X5,change=X6,attributes=X7}}) -> <<(enc_family(X1)):8/unsigned-native,0:8/unsigned-native,(enc_arphrd(X3)):16/unsigned-native,X4:32/signed-native,(netlink_codec:encode_flags(X5,fun enc_iff_flags/1)):32/unsigned-native,(netlink_codec:encode_flags(X6,fun enc_iff_flags/1)):32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_link(X7i) || X7i <- X7]))/binary>>. +dec_newneigh({native,<<X1e:8/unsigned-native,_:8/unsigned-native,_:16/unsigned-native,X4:32/unsigned-native,X5:16/unsigned-native,X6:8/unsigned-native,X7:8/unsigned-native,X8/binary>>}) -> + #newneigh{family=dec_family(X1e),index=X4,state=X5,flags=X6,nmd_type=X7,attributes=[dec_rtnetlink_neigh(X8i) || X8i <- netlink_codec:decode_tlv_list(X8)]}. +enc_newneigh({_Endian,#newneigh{family=X1,index=X4,state=X5,flags=X6,nmd_type=X7,attributes=X8}}) -> <<(enc_family(X1)):8/unsigned-native,0:8/unsigned-native,0:16/unsigned-native,X4:32/unsigned-native,X5:16/unsigned-native,X6:8/unsigned-native,X7:8/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_neigh(X8i) || X8i <- X8]))/binary>>. +dec_delneigh({native,<<X1e:8/unsigned-native,_:8/unsigned-native,_:16/unsigned-native,X4:32/unsigned-native,X5:16/unsigned-native,X6:8/unsigned-native,X7:8/unsigned-native,X8/binary>>}) -> + #delneigh{family=dec_family(X1e),index=X4,state=X5,flags=X6,nmd_type=X7,attributes=[dec_rtnetlink_neigh(X8i) || X8i <- netlink_codec:decode_tlv_list(X8)]}. +enc_delneigh({_Endian,#delneigh{family=X1,index=X4,state=X5,flags=X6,nmd_type=X7,attributes=X8}}) -> <<(enc_family(X1)):8/unsigned-native,0:8/unsigned-native,0:16/unsigned-native,X4:32/unsigned-native,X5:16/unsigned-native,X6:8/unsigned-native,X7:8/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_neigh(X8i) || X8i <- X8]))/binary>>. +dec_getneigh({native,<<X1e:8/unsigned-native,_:8/unsigned-native,_:16/unsigned-native,X4:32/unsigned-native,X5:16/unsigned-native,X6:8/unsigned-native,X7:8/unsigned-native,X8/binary>>}) -> + #getneigh{family=dec_family(X1e),index=X4,state=X5,flags=X6,nmd_type=X7,attributes=[dec_rtnetlink_neigh(X8i) || X8i <- netlink_codec:decode_tlv_list(X8)]}. +enc_getneigh({_Endian,#getneigh{family=X1,index=X4,state=X5,flags=X6,nmd_type=X7,attributes=X8}}) -> <<(enc_family(X1)):8/unsigned-native,0:8/unsigned-native,0:16/unsigned-native,X4:32/unsigned-native,X5:16/unsigned-native,X6:8/unsigned-native,X7:8/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_neigh(X8i) || X8i <- X8]))/binary>>. +dec_ifaddrmsg({native,<<X1e:8/unsigned-native,X2:8/unsigned-native,X3f:8/unsigned-native,X4:8/unsigned-native,X5:32/unsigned-native,X6/binary>>}) -> + #ifaddrmsg{family=dec_family(X1e),prefixlen=X2,flags=netlink_codec:decode_flags(X3f,fun dec_ifa_flags/1),scope=X4,index=X5,attributes=[dec_rtnetlink_addr(X6i) || X6i <- netlink_codec:decode_tlv_list(X6)]}. +enc_ifaddrmsg({_Endian,#ifaddrmsg{family=X1,prefixlen=X2,flags=X3,scope=X4,index=X5,attributes=X6}}) -> <<(enc_family(X1)):8/unsigned-native,X2:8/unsigned-native,(netlink_codec:encode_flags(X3,fun enc_ifa_flags/1)):8/unsigned-native,X4:8/unsigned-native,X5:32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_addr(X6i) || X6i <- X6]))/binary>>. +dec_ifinfomsg({native,<<X1e:8/unsigned-native,_:8/unsigned-native,X3e:16/unsigned-native,X4:32/signed-native,X5f:32/unsigned-native,X6f:32/unsigned-native,X7/binary>>}) -> + #ifinfomsg{family=dec_family(X1e),arphrd=dec_arphrd(X3e),index=X4,flags=netlink_codec:decode_flags(X5f,fun dec_iff_flags/1),change=netlink_codec:decode_flags(X6f,fun dec_iff_flags/1),attributes=[dec_rtnetlink_link(X7i) || X7i <- netlink_codec:decode_tlv_list(X7)]}. +enc_ifinfomsg({_Endian,#ifinfomsg{family=X1,arphrd=X3,index=X4,flags=X5,change=X6,attributes=X7}}) -> <<(enc_family(X1)):8/unsigned-native,0:8/unsigned-native,(enc_arphrd(X3)):16/unsigned-native,X4:32/signed-native,(netlink_codec:encode_flags(X5,fun enc_iff_flags/1)):32/unsigned-native,(netlink_codec:encode_flags(X6,fun enc_iff_flags/1)):32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_link(X7i) || X7i <- X7]))/binary>>. +dec_rtmsg({native,<<X1e:8/unsigned-native,X2:8/unsigned-native,X3:8/unsigned-native,X4:8/unsigned-native,X5:8/unsigned-native,X6e:8/unsigned-native,X7:8/unsigned-native,X8:8/unsigned-native,X9:32/unsigned-native,X10/binary>>}) -> + #rtmsg{family=dec_family(X1e),dstlen=X2,srclen=X3,tos=X4,table=X5,protocol=dec_protocol(X6e),scope=X7,rtm_type=X8,flags=X9,attributes=[dec_rtnetlink_route(X10i) || X10i <- netlink_codec:decode_tlv_list(X10)]}. +enc_rtmsg({_Endian,#rtmsg{family=X1,dstlen=X2,srclen=X3,tos=X4,table=X5,protocol=X6,scope=X7,rtm_type=X8,flags=X9,attributes=X10}}) -> <<(enc_family(X1)):8/unsigned-native,X2:8/unsigned-native,X3:8/unsigned-native,X4:8/unsigned-native,X5:8/unsigned-native,(enc_protocol(X6)):8/unsigned-native,X7:8/unsigned-native,X8:8/unsigned-native,X9:32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_route(X10i) || X10i <- X10]))/binary>>. +dec_ndmsg({native,<<X1e:8/unsigned-native,_:8/unsigned-native,_:16/unsigned-native,X4:32/unsigned-native,X5:16/unsigned-native,X6:8/unsigned-native,X7:8/unsigned-native,X8/binary>>}) -> + #ndmsg{family=dec_family(X1e),index=X4,state=X5,flags=X6,nmd_type=X7,attributes=[dec_rtnetlink_neigh(X8i) || X8i <- netlink_codec:decode_tlv_list(X8)]}. +enc_ndmsg({_Endian,#ndmsg{family=X1,index=X4,state=X5,flags=X6,nmd_type=X7,attributes=X8}}) -> <<(enc_family(X1)):8/unsigned-native,0:8/unsigned-native,0:16/unsigned-native,X4:32/unsigned-native,X5:16/unsigned-native,X6:8/unsigned-native,X7:8/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_neigh(X8i) || X8i <- X8]))/binary>>. +dec_newroute({native,<<X1e:8/unsigned-native,X2:8/unsigned-native,X3:8/unsigned-native,X4:8/unsigned-native,X5:8/unsigned-native,X6e:8/unsigned-native,X7:8/unsigned-native,X8:8/unsigned-native,X9:32/unsigned-native,X10/binary>>}) -> + #newroute{family=dec_family(X1e),dstlen=X2,srclen=X3,tos=X4,table=X5,protocol=dec_protocol(X6e),scope=X7,rtm_type=X8,flags=X9,attributes=[dec_rtnetlink_route(X10i) || X10i <- netlink_codec:decode_tlv_list(X10)]}. +enc_newroute({_Endian,#newroute{family=X1,dstlen=X2,srclen=X3,tos=X4,table=X5,protocol=X6,scope=X7,rtm_type=X8,flags=X9,attributes=X10}}) -> <<(enc_family(X1)):8/unsigned-native,X2:8/unsigned-native,X3:8/unsigned-native,X4:8/unsigned-native,X5:8/unsigned-native,(enc_protocol(X6)):8/unsigned-native,X7:8/unsigned-native,X8:8/unsigned-native,X9:32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_route(X10i) || X10i <- X10]))/binary>>. +dec_delroute({native,<<X1e:8/unsigned-native,X2:8/unsigned-native,X3:8/unsigned-native,X4:8/unsigned-native,X5:8/unsigned-native,X6e:8/unsigned-native,X7:8/unsigned-native,X8:8/unsigned-native,X9:32/unsigned-native,X10/binary>>}) -> + #delroute{family=dec_family(X1e),dstlen=X2,srclen=X3,tos=X4,table=X5,protocol=dec_protocol(X6e),scope=X7,rtm_type=X8,flags=X9,attributes=[dec_rtnetlink_route(X10i) || X10i <- netlink_codec:decode_tlv_list(X10)]}. +enc_delroute({_Endian,#delroute{family=X1,dstlen=X2,srclen=X3,tos=X4,table=X5,protocol=X6,scope=X7,rtm_type=X8,flags=X9,attributes=X10}}) -> <<(enc_family(X1)):8/unsigned-native,X2:8/unsigned-native,X3:8/unsigned-native,X4:8/unsigned-native,X5:8/unsigned-native,(enc_protocol(X6)):8/unsigned-native,X7:8/unsigned-native,X8:8/unsigned-native,X9:32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_route(X10i) || X10i <- X10]))/binary>>. +dec_getroute({native,<<X1e:8/unsigned-native,X2:8/unsigned-native,X3:8/unsigned-native,X4:8/unsigned-native,X5:8/unsigned-native,X6e:8/unsigned-native,X7:8/unsigned-native,X8:8/unsigned-native,X9:32/unsigned-native,X10/binary>>}) -> + #getroute{family=dec_family(X1e),dstlen=X2,srclen=X3,tos=X4,table=X5,protocol=dec_protocol(X6e),scope=X7,rtm_type=X8,flags=X9,attributes=[dec_rtnetlink_route(X10i) || X10i <- netlink_codec:decode_tlv_list(X10)]}. +enc_getroute({_Endian,#getroute{family=X1,dstlen=X2,srclen=X3,tos=X4,table=X5,protocol=X6,scope=X7,rtm_type=X8,flags=X9,attributes=X10}}) -> <<(enc_family(X1)):8/unsigned-native,X2:8/unsigned-native,X3:8/unsigned-native,X4:8/unsigned-native,X5:8/unsigned-native,(enc_protocol(X6)):8/unsigned-native,X7:8/unsigned-native,X8:8/unsigned-native,X9:32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_route(X10i) || X10i <- X10]))/binary>>. +dec_done({native,<<X1:32/unsigned-native>>}) -> + #done{status=X1}. +enc_done({_Endian,#done{status=X1}}) -> <<X1:32/unsigned-native>>. +dec_nlmsghdr({native,<<X1:32/unsigned-native,X2:16/unsigned-native,X3:16/unsigned-native,X4:32/unsigned-native,X5:32/unsigned-native>>}) -> + #nlmsghdr{len=X1,type=X2,flags=X3,seq=X4,pid=X5}. +enc_nlmsghdr({_Endian,#nlmsghdr{len=X1,type=X2,flags=X3,seq=X4,pid=X5}}) -> <<X1:32/unsigned-native,X2:16/unsigned-native,X3:16/unsigned-native,X4:32/unsigned-native,X5:32/unsigned-native>>. +dec_newaddr({native,<<X1e:8/unsigned-native,X2:8/unsigned-native,X3f:8/unsigned-native,X4:8/unsigned-native,X5:32/unsigned-native,X6/binary>>}) -> + #newaddr{family=dec_family(X1e),prefixlen=X2,flags=netlink_codec:decode_flags(X3f,fun dec_ifa_flags/1),scope=X4,index=X5,attributes=[dec_rtnetlink_addr(X6i) || X6i <- netlink_codec:decode_tlv_list(X6)]}. +enc_newaddr({_Endian,#newaddr{family=X1,prefixlen=X2,flags=X3,scope=X4,index=X5,attributes=X6}}) -> <<(enc_family(X1)):8/unsigned-native,X2:8/unsigned-native,(netlink_codec:encode_flags(X3,fun enc_ifa_flags/1)):8/unsigned-native,X4:8/unsigned-native,X5:32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_addr(X6i) || X6i <- X6]))/binary>>. +dec_deladdr({native,<<X1e:8/unsigned-native,X2:8/unsigned-native,X3f:8/unsigned-native,X4:8/unsigned-native,X5:32/unsigned-native,X6/binary>>}) -> + #deladdr{family=dec_family(X1e),prefixlen=X2,flags=netlink_codec:decode_flags(X3f,fun dec_ifa_flags/1),scope=X4,index=X5,attributes=[dec_rtnetlink_addr(X6i) || X6i <- netlink_codec:decode_tlv_list(X6)]}. +enc_deladdr({_Endian,#deladdr{family=X1,prefixlen=X2,flags=X3,scope=X4,index=X5,attributes=X6}}) -> <<(enc_family(X1)):8/unsigned-native,X2:8/unsigned-native,(netlink_codec:encode_flags(X3,fun enc_ifa_flags/1)):8/unsigned-native,X4:8/unsigned-native,X5:32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_addr(X6i) || X6i <- X6]))/binary>>. +dec_getaddr({native,<<X1e:8/unsigned-native,X2:8/unsigned-native,X3f:8/unsigned-native,X4:8/unsigned-native,X5:32/unsigned-native,X6/binary>>}) -> + #getaddr{family=dec_family(X1e),prefixlen=X2,flags=netlink_codec:decode_flags(X3f,fun dec_ifa_flags/1),scope=X4,index=X5,attributes=[dec_rtnetlink_addr(X6i) || X6i <- netlink_codec:decode_tlv_list(X6)]}. +enc_getaddr({_Endian,#getaddr{family=X1,prefixlen=X2,flags=X3,scope=X4,index=X5,attributes=X6}}) -> <<(enc_family(X1)):8/unsigned-native,X2:8/unsigned-native,(netlink_codec:encode_flags(X3,fun enc_ifa_flags/1)):8/unsigned-native,X4:8/unsigned-native,X5:32/unsigned-native,(netlink_codec:encode_tlv_list([enc_rtnetlink_addr(X6i) || X6i <- X6]))/binary>>. +dec_error({native,<<X1:32/signed-native,X21:32/unsigned-native,X22:16/unsigned-native,X23:16/unsigned-native,X24:32/unsigned-native,X25:32/unsigned-native,X3/binary>>}) -> + #error{errno=X1,msg=#nlmsghdr{len=X21,type=X22,flags=X23,seq=X24,pid=X25},data=X3}. +enc_error({_Endian,#error{errno=X1,msg=#nlmsghdr{len=X21,type=X22,flags=X23,seq=X24,pid=X25},data=X3}}) -> <<X1:32/signed-native,X21:32/unsigned-native,X22:16/unsigned-native,X23:16/unsigned-native,X24:32/unsigned-native,X25:32/unsigned-native,X3>>. +dec_if_map({native,<<X1:64/unsigned-native,X2:64/unsigned-native,X3:64/unsigned-native,X4:16/unsigned-native,X5:8/unsigned-native,X6:8/unsigned-native>>}) -> + #if_map{memstart=X1,memend=X2,baseaddr=X3,irq=X4,dma=X5,port=X6}. +enc_if_map({_Endian,#if_map{memstart=X1,memend=X2,baseaddr=X3,irq=X4,dma=X5,port=X6}}) -> <<X1:64/unsigned-native,X2:64/unsigned-native,X3:64/unsigned-native,X4:16/unsigned-native,X5:8/unsigned-native,X6:8/unsigned-native>>. +dec_noop({native,<<>>}) -> + #noop{}. +enc_noop({_Endian,#noop{}}) -> <<>>. diff --git a/deps/netlink/src/netl_codec.hrl b/deps/netlink/src/netl_codec.hrl new file mode 100644 index 0000000..a5bcf47 --- /dev/null +++ b/deps/netlink/src/netl_codec.hrl @@ -0,0 +1,200 @@ +-define(AF_ATMPVC, 8). +-define(AF_ATMSVC, 20). +-define(ARPHRD_CHAOS, 5). +-define(ARPHRD_RAWHDLC, 518). +-define(RTM_DELADDR, 21). +-define(RTM_GETADDR, 22). +-define(ARPHRD_IEEE802, 6). +-define(AF_SNA, 22). +-define(NLMSG_NOOP, 1). +-define(PROTO_ICMP, 1). +-define(PROTO_IGMP, 2). +-define(PROTO_IPIP, 4). +-define(PROTO_UDP, 17). +-define(PROTO_IDP, 22). +-define(PROTO_MTP, 92). +-define(PROTO_COMP, 108). +-define(ARPHRD_ETHER , 1). +-define(ARPHRD_CISCO, 513). +-define(IPCTNL_MSG_CT_GET_CTRZERO, 3). +-define(AF_CAN, 29). +-define(ARPHRD_CAN, 280). +-define(AF_NETROM, 6). +-define(ARPHRD_NETROM, 0). +-define(ARPHRD_METRICOM, 23). +-define(RTM_NEWNEIGHTBL, 64). +-define(RTM_GETNEIGHTBL, 66). +-define(RTM_SETNEIGHTBL, 67). +-define(ARPHRD_TUNNEL, 768). +-define(ARPHRD_FCPL, 786). +-define(RTM_DELLINK, 17). +-define(RTM_GETLINK, 18). +-define(AF_APPLETALK, 5). +-define(ARPHRD_APPLETLK, 8). +-define(ARPHRD_LOOPBACK, 772). +-define(AF_NETBEUI, 13). +-define(ARPHRD_FDDI, 774). +-define(RTM_NEWNEIGH, 28). +-define(RTM_DELNEIGH, 29). +-define(RTM_GETNEIGH, 30). +-define(RTM_NEWPREFIX, 52). +-define(AF_IPX, 4). +-define(AF_ASH, 18). +-define(AF_PPPOX, 24). +-define(AF_BLUETOOTH, 31). +-define(ARPHRD_ASH, 781). +-define(PROTO_ROUTING, 43). +-define(PROTO_RAW, 255). +-define(ARPHRD_PIMREG, 779). +-define(PROTO_IPV6, 41). +-define(ARPHRD_SLIP6, 258). +-define(ARPHRD_CSLIP6, 259). +-define(ARPHRD_TUNNEL6, 769). +-define(ARPHRD_BIF, 775). +-define(RTM_GETROUTE, 26). +-define(RTM_DELRULE, 33). +-define(RTM_GETRULE, 34). +-define(AF_AX25, 3). +-define(AF_BRIDGE, 7). +-define(AF_X25, 9). +-define(AF_ROSE, 11). +-define(AF_ROUTE, 16). +-define(PROTO_GRE, 47). +-define(PROTO_UDPLITE, 136). +-define(ARPHRD_X25, 271). +-define(ARPHRD_HWX25, 272). +-define(ARPHRD_NONE, 65534). +-define(RTM_GETMULTICAST, 58). +-define(RTM_GETANYCAST, 62). +-define(RTM_NEWNDUSEROPT, 68). +-define(AF_IEEE802154, 36). +-define(PROTO_FRAGMENT, 44). +-define(ARPHRD_EUI64, 27). +-define(ARPHRD_INFINIBAND, 32). +-define(ARPHRD_ADAPT, 264). +-define(RTM_NEWQDISC, 36). +-define(RTM_DELQDISC, 37). +-define(RTM_NEWTCLASS, 40). +-define(RTM_DELTCLASS, 41). +-define(RTM_GETTCLASS, 42). +-define(AF_UNSPEC, 0). +-define(AF_RDS, 21). +-define(AF_RXRPC, 33). +-define(PROTO_DSTOPTS, 60). +-define(ARPHRD_HDLC, 513). +-define(NLMSG_ERROR, 2). +-define(RTM_NEWADDR, 20). +-define(RTM_NEWTFILTER, 44). +-define(ARPHRD_LAPB, 516). +-define(ARPHRD_IEEE802_TR, 800). +-define(ARPHRD_IRDA, 783). +-define(ARPHRD_IEEE80211, 801). +-define(PROTO_IP, 0). +-define(PROTO_TCP, 6). +-define(PROTO_EGP, 8). +-define(PROTO_PUP, 12). +-define(PROTO_RSVP, 46). +-define(PROTO_ESP, 50). +-define(PROTO_ENCAP, 98). +-define(PROTO_SCTP, 132). +-define(ARPHRD_SLIP, 256). +-define(ARPHRD_PPP, 512). +-define(ARPHRD_SKIP, 771). +-define(ARPHRD_IPDDP, 777). +-define(ARPHRD_IEEE80211_RADIOTAP, 803). +-define(NLMSG_OVERRUN, 4). +-define(RTM_NEWACTION, 48). +-define(RTM_DELACTION, 49). +-define(RTM_GETACTION, 50). +-define(AF_ISDN, 34). +-define(PROTO_PIM, 103). +-define(ARPHRD_ATM, 19). +-define(ARPHRD_IEEE80211_PRISM, 802). +-define(RTM_NEWADDRLABEL, 72). +-define(RTM_DELADDRLABEL, 73). +-define(RTM_GETADDRLABEL, 74). +-define(AF_LOCAL, 1). +-define(ARPHRD_FCAL, 785). +-define(RTM_NEWLINK, 16). +-define(RTM_SETLINK, 19). +-define(AF_NETLINK, 16). +-define(ARPHRD_LOCALTLK, 773). +-define(AF_SECURITY, 14). +-define(AF_KEY, 15). +-define(ARPHRD_DLCI, 15). +-define(ARPHRD_HIPPI, 780). +-define(AF_UNIX, 1). +-define(PROTO_AH, 51). +-define(IPCTNL_MSG_CT_NEW, 0). +-define(IPCTNL_MSG_EXP_NEW, 0). +-define(AF_INET6, 10). +-define(AF_IUCV, 32). +-define(PROTO_ICMPV6, 58). +-define(ARPHRD_CAIF, 822). +-define(NLMSG_DONE, 3). +-define(RTM_NEWROUTE, 24). +-define(RTM_DELROUTE, 25). +-define(RTM_NEWRULE, 32). +-define(AF_FILE, 1). +-define(AF_WANPIPE, 25). +-define(PROTO_NONE, 59). +-define(ARPHRD_AX25, 3). +-define(ARPHRD_ROSE, 270). +-define(ARPHRD_IPGRE, 778). +-define(ARPHRD_PHONET_PIPE, 821). +-define(IPCTNL_MSG_CT_DELETE, 2). +-define(IPCTNL_MSG_EXP_DELETE, 2). +-define(AF_INET, 2). +-define(AF_DECNET, 12). +-define(AF_PACKET, 17). +-define(AF_ECONET, 19). +-define(AF_PHONET, 35). +-define(ARPHRD_PRONET, 4). +-define(ARPHRD_ARCNET, 7). +-define(ARPHRD_IEEE1394, 24). +-define(ARPHRD_RSRVD, 260). +-define(ARPHRD_FRAD, 770). +-define(ARPHRD_SIT, 776). +-define(ARPHRD_ECONET, 782). +-define(ARPHRD_IEEE802154, 804). +-define(ARPHRD_PHONET, 820). +-define(ARPHRD_VOID, 65535). +-define(IPCTNL_MSG_CT_GET, 1). +-define(IPCTNL_MSG_EXP_GET, 1). +-define(RTM_GETQDISC, 38). +-define(AF_LLC, 26). +-define(AF_TIPC, 30). +-define(ARPHRD_FCFABRIC, 787). +-define(RTM_DELTFILTER, 45). +-define(RTM_GETTFILTER, 46). +-define(RTM_GETDCB, 78). +-define(RTM_SETDCB, 79). +-define(ARPHRD_EETHER, 2). +-define(AF_IRDA, 23). +-define(PROTO_TP, 29). +-define(PROTO_DCCP, 33). +-define(ARPHRD_CSLIP, 257). +-define(ARPHRD_DDCMP, 517). +-define(ARPHRD_FCPP, 784). +-record(overrun, {status}). +-record(newlink, {family,arphrd,index,flags,change,attributes}). +-record(dellink, {family,arphrd,index,flags,change,attributes}). +-record(getlink, {family,arphrd,index,flags,change,attributes}). +-record(newneigh, {family,index,state,flags,nmd_type,attributes}). +-record(delneigh, {family,index,state,flags,nmd_type,attributes}). +-record(getneigh, {family,index,state,flags,nmd_type,attributes}). +-record(ifaddrmsg, {family,prefixlen,flags,scope,index,attributes}). +-record(ifinfomsg, {family,arphrd,index,flags,change,attributes}). +-record(rtmsg, {family,dstlen,srclen,tos,table,protocol,scope,rtm_type,flags,attributes}). +-record(ndmsg, {family,index,state,flags,nmd_type,attributes}). +-record(newroute, {family,dstlen,srclen,tos,table,protocol,scope,rtm_type,flags,attributes}). +-record(delroute, {family,dstlen,srclen,tos,table,protocol,scope,rtm_type,flags,attributes}). +-record(getroute, {family,dstlen,srclen,tos,table,protocol,scope,rtm_type,flags,attributes}). +-record(done, {status}). +-record(nlmsghdr, {len,type,flags,seq,pid}). +-record(newaddr, {family,prefixlen,flags,scope,index,attributes}). +-record(deladdr, {family,prefixlen,flags,scope,index,attributes}). +-record(getaddr, {family,prefixlen,flags,scope,index,attributes}). +-record(error, {errno,msg,data}). +-record(if_map, {memstart,memend,baseaddr,irq,dma,port}). +-record(noop, {}). diff --git a/deps/netlink/src/netlink.app.src b/deps/netlink/src/netlink.app.src new file mode 100644 index 0000000..1025181 --- /dev/null +++ b/deps/netlink/src/netlink.app.src @@ -0,0 +1,12 @@ +{application, netlink, + [ + {description, ""}, + {vsn, "1"}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]}, + {mod, { netlink_app, []}}, + {env, []} + ]}. diff --git a/deps/netlink/src/netlink.erl b/deps/netlink/src/netlink.erl new file mode 100644 index 0000000..bd08477 --- /dev/null +++ b/deps/netlink/src/netlink.erl @@ -0,0 +1,737 @@ +%%%---- BEGIN COPYRIGHT ------------------------------------------------------- +%%% +%%% Copyright (C) 2012 Feuerlabs, Inc. All rights reserved. +%%% +%%% This Source Code Form is subject to the terms of the Mozilla Public +%%% License, v. 2.0. If a copy of the MPL was not distributed with this +%%% file, You can obtain one at http://mozilla.org/MPL/2.0/. +%%% +%%%---- END COPYRIGHT --------------------------------------------------------- +%%%------------------------------------------------------------------- +%%% @author Tony Rogvall <tony@rogvall.se> +%%% @doc +%%% Netlink state monitor +%%% @end +%%% Created : 11 Jun 2012 by Tony Rogvall <tony@rogvall.se> +%%%------------------------------------------------------------------- +-module(netlink). + +-behaviour(gen_server). + +%% API +-export([start_link/0, start_link/1]). +-export([start/0, stop/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). +-export([i/0, list/1]). +-export([subscribe/1, subscribe/2, subscribe/3]). +-export([unsubscribe/1]). +-export([invalidate/2]). +-export([get_root/2, get_match/3, get/4]). + +-include("log.hrl"). +-include("netlink.hrl"). +-include("netl_codec.hrl"). + +-define(SERVER, ?MODULE). + +-type if_addr_field() :: address | local | broadcast | anycast | multicast. + +-type if_link_field() :: name | index | mtu | txqlen | flags | + operstate | qdisc | address | broadcast. + +-type uint8_t() :: 0..16#ff. +-type uint16_t() :: 0..16#ffff. + +-type ipv4_addr() :: {uint8_t(),uint8_t(),uint8_t(),uint8_t()}. +-type ipv6_addr() :: {uint16_t(),uint16_t(),uint16_t(),uint16_t(), + uint16_t(),uint16_t(),uint16_t(),uint16_t()}. + +-type if_addr() :: ipv4_addr() | ipv6_addr(). + +-type if_field() :: if_link_field() | if_addr_field() | + {link,if_link_field()} | {addr,if_addr_field()}. + +-type if_name() :: string(). + + +-record(link, + { + name :: if_name(), %% interface name + index :: non_neg_integer(), %% interface index + attr :: term() %% attributes {atom(),term} + }). + +-record(addr, + { + addr :: if_addr(), %% the address + name :: if_name(), %% interface label + index :: non_neg_integer(), %% interface index + attr :: term() %% attributes + }). + +-record(subscription, + { + pid :: pid(), %% subscriber + mon :: reference(), %% monitor + name :: string(), %% name + fields=all :: all | addr | link | [if_field()] + }). + +-define(MIN_RCVBUF, (128*1024)). +-define(MIN_SNDBUF, (32*1024)). + +-define(REQUEST_TMO, 2000). + +-record(request, + { + tmr, %% timer reference + call, %% call request + from, %% caller + reply=ok, %% reply to send when done + seq=0 %% sequence to expect in reply + }). + +-record(state, + { + port, + link_list = [] :: [#link {}], + addr_list = [] :: [#addr {}], + sub_list = [] :: [#subscription {}], + request :: undefined | #request{}, + request_queue = [] :: [#request{}], + o_seq = 0, + i_seq = 0, + ospid + }). + +%%%=================================================================== +%%% API +%%%=================================================================== + +start() -> + application:start(netlink). + +i() -> + gen_server:call(?SERVER, {list,[]}). + +stop() -> + gen_server:call(?SERVER, stop). + +list(Match) -> + gen_server:call(?SERVER, {list,Match}). + +%% @doc +%% Subscribe to interface changes, notifications will be +%% sent in {netlink,reference(),if_name(),if_field(),OldValue,NewValue} +%% @end + +-spec subscribe(Name::string()) -> + {ok,reference()}. + +subscribe(Name) -> + subscribe(Name,all,[]). + +-spec subscribe(Name::string(),Fields::all|[if_field()]) -> + {ok,reference()}. + +subscribe(Name,Fields) -> + subscribe(Name,Fields, []). + +-spec subscribe(Name::string(),Fields::all|[if_field()],Otions::[atom()]) -> + {ok,reference()}. +subscribe(Name,Fields,Options) -> + gen_server:call(?SERVER, {subscribe, self(),Name,Options,Fields}). + +unsubscribe(Ref) -> + gen_server:call(?SERVER, {unsubscribe,Ref}). + +%% clear all attributes for interface Name +invalidate(Name,Fields) -> + gen_server:call(?SERVER, {invalidate,Name,Fields}). + +get_root(What,Fam) -> + get(What,Fam,[root,match,request],[]). + +get_match(What,Fam,GetAttrs) -> + get(What,Fam,[match,request],GetAttrs). + +get(What,Fam,GetFlags,GetAttrs) -> + gen_server:call(?SERVER, {get,What,Fam,GetFlags,GetAttrs}). + +%%-------------------------------------------------------------------- +%% @doc +%% Starts the server +%% +%% @spec start_link() -> {ok, Pid} | ignore | {error, Error} +%% @end +%%-------------------------------------------------------------------- +start_link() -> + start_link([]). +start_link(Opts) -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [Opts], []). + +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Initializes the server +%% +%% @spec init(Args) -> {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%% @end +%%-------------------------------------------------------------------- +init([Opts]) -> + OsPid = list_to_integer(os:getpid()), + I_Seq = O_Seq = 1234, %% element(2,now()), + State = #state{ ospid = OsPid, + o_seq = O_Seq, + i_seq = I_Seq }, + + case os:type() of + {unix, linux} -> + init_drv(Opts, State); + _ -> + {ok, State} + end. + +init_drv(Opts, State) -> + Port = netlink_drv:open(?NETLINK_ROUTE), + + netlink_drv:debug(Port, proplists:get_value(debug,Opts,none)), + + {ok,Rcvbuf} = update_rcvbuf(Port, ?MIN_RCVBUF), + {ok,Sndbuf} = update_sndbuf(Port, ?MIN_SNDBUF), + + ?info("Rcvbuf: ~w, Sndbuf: ~w", [Rcvbuf, Sndbuf]), + + {ok,Sizes} = netlink_drv:get_sizeof(Port), + ?info("Sizes: ~w", [Sizes]), + + ok = netlink_drv:add_membership(Port, ?RTNLGRP_LINK), + ok = netlink_drv:add_membership(Port, ?RTNLGRP_IPV4_IFADDR), + ok = netlink_drv:add_membership(Port, ?RTNLGRP_IPV6_IFADDR), + + netlink_drv:activate(Port), + %% init sequence to fill the cache + T0 = erlang:start_timer(200, self(), request_timeout), + R0 = #request { tmr = T0, + call = noop, + from = {self(),make_ref()} + }, + R1 = #request { tmr = {relative, ?REQUEST_TMO}, + call = {get,link,unspec, + [root,match,request], + []}, + from = {self(),make_ref()} + }, + R2 = #request { tmr = {relative, 1000}, + call = noop, + from = {self(),make_ref()} + }, + R3 = #request { tmr = {relative,?REQUEST_TMO}, + call = {get,addr,unspec, + [root,match,request], + []}, + from = {self(),make_ref()} + }, + {ok, State#state{ port=Port, + request = R0, + request_queue = [R1,R2,R3] + }}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Handling call messages +%% +%% @spec handle_call(Request, From, State) -> +%% {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | +%% {stop, Reason, State} +%% @end +%%-------------------------------------------------------------------- +handle_call({list,Match}, _From, State) -> + lists:foreach( + fun(L) -> + %% select addresses that belong to link L + Ys = [Y || Y <- State#state.addr_list, + Y#addr.index =:= L#link.index], + FYs = [format_addr(Y) || Y <- Ys ], + case match(L#link.attr,dict:new(),Match) of + true -> + io:format("link {~s~s}\n", + [FYs,format_link(L)]); + false -> + ok + end + end, State#state.link_list), + {reply, ok, State}; +handle_call({subscribe, Pid, Name, Options, Fs}, _From, State) -> + Mon = erlang:monitor(process, Pid), + S = #subscription { pid=Pid, mon=Mon, name=Name, fields=Fs }, + SList = [S | State#state.sub_list], + case proplists:get_bool(flush, Options) of + false -> + {reply, {ok,Mon}, State#state { sub_list = SList }}; + true -> + lists:foreach( + fun(L) -> + As = dict:to_list(L#link.attr), + update_attrs(L#link.name, link, As, dict:new(), [S]) + end, State#state.link_list), + lists:foreach( + fun(Y) -> + As = dict:to_list(Y#addr.attr), + update_attrs(Y#addr.name, addr, As, dict:new(), [S]) + end, State#state.addr_list), + {reply, {ok,Mon}, State#state { sub_list = SList }} + end; +handle_call({unsubscribe,Ref}, _From, State) -> + case lists:keytake(Ref, #subscription.mon, State#state.sub_list) of + false -> + {reply,ok,State}; + {value,_S,SubList} -> + erlang:demonitor(Ref), + {reply,ok,State#state { sub_list=SubList }} + end; +handle_call({invalidate,Name,Fields},_From,State) -> + case lists:keytake(Name, #link.name, State#state.link_list) of + false -> {reply, {error,enoent}, State}; + {value,L,Ls} -> + Attr = lists:foldl( + fun(F,D) when is_atom(F) -> + dict:erase(F, D) + end, L#link.attr, Fields), + L1 = L#link { attr = Attr }, + {reply, ok, State#state { link_list = [L1|Ls] } } + end; + +handle_call(Req={get,_What,_Fam,_Flags,_Attrs}, From, State) -> + ?debug("handle_call: GET: ~p", [Req]), + State1 = enq_request(Req, From, State), + State2 = dispatch_command(State1), + {noreply, State2}; +handle_call(stop, _From, State) -> + {stop, normal, ok, State}; +handle_call(_Request, _From, State) -> + Reply = ok, + {reply, Reply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Handling cast messages +%% +%% @spec handle_cast(Msg, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% @end +%%-------------------------------------------------------------------- +handle_cast(_Msg, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Handling all non call/cast messages +%% +%% @spec handle_info(Info, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% @end +%%-------------------------------------------------------------------- + +handle_info(_Info={nl_data,Port,Data},State) when Port =:= State#state.port -> + try netlink_codec:decode(Data,[]) of + MsgList -> + %% FIXME: the messages should be delivered one by one from + %% the driver so the decoding could simplified. + State1 = + lists:foldl( + fun(Msg,StateI) -> + ?debug("handle_info: msg=~p", [Msg]), + _Hdr = Msg#nlmsg.hdr, + MsgData = Msg#nlmsg.data, + handle_nlmsg(MsgData, StateI) + end, State, MsgList), + {noreply, State1} + catch + error:_ -> + ?error("netlink: handle_info: Crash: ~p", + [erlang:get_stacktrace()]), + {noreply, State} + end; + +handle_info({'DOWN',Ref,process,Pid,Reason}, State) -> + case lists:keytake(Ref, #subscription.mon, State#state.sub_list) of + false -> + {noreply,State}; + {value,_S,SubList} -> + ?debug("subscription from pid ~p deleted reason=~p", + [Pid, Reason]), + {noreply,State#state { sub_list=SubList }} + end; +handle_info({timeout,Tmr,request_timeout}, State) -> + R = State#state.request, + if R#request.tmr =:= Tmr -> + ?debug("Timeout: ref current", []), + gen_server:reply(R#request.from, {error,timeout}), + State1 = State#state { request = undefined }, + {noreply, dispatch_command(State1)}; + true -> + case lists:keytake(Tmr, #request.tmr, State#state.request_queue) of + false -> + ?debug("Timeout: ref not found", []), + {noreply, State}; + {value,#request { from = From},Q} -> + ?debug("Timeout: ref in queue", []), + gen_server:reply(From, {error,timeout}), + State1 = State#state { request_queue = Q }, + {noreply,dispatch_command(State1)} + end + end; +handle_info({Tag, Reply}, State) when is_reference(Tag) -> + ?debug("INFO: SELF Reply=~p", [Reply]), + {noreply, State}; +handle_info(_Info, State) -> + ?debug("INFO: ~p", [_Info]), + {noreply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% This function is called by a gen_server when it is about to +%% terminate. It should be the opposite of Module:init/1 and do any +%% necessary cleaning up. When it returns, the gen_server terminates +%% with Reason. The return value is ignored. +%% +%% @spec terminate(Reason, State) -> void() +%% @end +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Convert process state when code is changed +%% +%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState} +%% @end +%%-------------------------------------------------------------------- +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== + +enq_request(Call, From, State) -> + Tmr = erlang:start_timer(?REQUEST_TMO, self(), request_timeout), + R = #request { tmr = Tmr, + call = Call, + from = From + }, + Q = State#state.request_queue ++ [R], + State#state { request_queue = Q }. + +dispatch_command(State) when State#state.request =:= undefined -> + case State#state.request_queue of + [R=#request { call = {get,What,Fam,Flags,Attrs} } | Q ] -> + R1 = update_timer(R), + State1 = State#state { request_queue = Q, request = R1 }, + ?debug("dispatch_command: ~p", [R1]), + get_command(What,Fam,Flags,Attrs,State1); + [R=#request { call = noop } | Q ] -> + R1 = update_timer(R), + State1 = State#state { request_queue = Q, request = R1 }, + ?debug("dispatch_command: ~p", [R1]), + State1; %% let it timeout + [] -> + State + end; +dispatch_command(State) -> + State. + +update_timer(R = #request { tmr = {relative,Tmo} }) + when is_integer(Tmo), Tmo >= 0 -> + Tmr = erlang:start_timer(Tmo, self(), request_timeout), + R#request { tmr = Tmr }; +update_timer(R = #request { tmr = Tmr }) when is_reference(Tmr) -> + R. + +update_sndbuf(Port, Min) -> + case netlink_drv:get_sndbuf(Port) of + {ok,Size} when Size >= Min -> + {ok,Size}; + {ok,_Size} -> + netlink_drv:set_sndbuf(Port, Min), + netlink_drv:get_sndbuf(Port); + Err -> Err + end. + + +update_rcvbuf(Port, Min) -> + case netlink_drv:get_rcvbuf(Port) of + {ok,Size} when Size >= Min -> + {ok,Size}; + {ok,_Size} -> + netlink_drv:set_rcvbuf(Port, Min), + netlink_drv:get_rcvbuf(Port); + Err -> Err + end. + +get_command(link,Fam,Flags,Attrs,State) -> + Seq = State#state.o_seq, + Get = #getlink{family=Fam,arphrd=ether,index=0, + flags=[], change=[], attributes=Attrs}, + Hdr = #nlmsghdr { type = getlink, + flags = Flags, + seq = Seq, + pid = State#state.ospid }, + Request = netlink_codec:encode(Hdr,Get), + netlink_drv:send(State#state.port, Request), + State#state { o_seq = (Seq+1) band 16#ffffffff }; +get_command(addr,Fam,Flags,Attrs,State) -> + Seq = State#state.o_seq, + Get = #getaddr{family=Fam,prefixlen=0,flags=[],scope=0, + index=0,attributes=Attrs}, + Hdr = #nlmsghdr { type=getaddr, + flags=Flags, + seq=Seq, + pid=State#state.ospid }, + Request = netlink_codec:encode(Hdr,Get), + netlink_drv:send(State#state.port, Request), + State#state { o_seq = (Seq+1) band 16#ffffffff}. + +handle_nlmsg(RTM=#newlink{family=_Fam,index=Index,flags=Fs,change=Cs, + attributes=As}, State) -> + ?debug("RTM = ~p", [RTM]), + Name = proplists:get_value(ifname, As, ""), + As1 = [{index,Index},{flags,Fs},{change,Cs}|As], + case lists:keytake(Index, #link.index, State#state.link_list) of + false -> + Attr = update_attrs(Name, link, As1, dict:new(), State#state.sub_list), + L = #link { index = Index, name = Name, attr = Attr }, + Ls = [L|State#state.link_list], + State#state { link_list = Ls }; + {value,L,Ls} -> + Attr = update_attrs(Name, link, As1, L#link.attr, State#state.sub_list), + L1 = L#link { name = Name, attr = Attr }, + State#state { link_list = [L1|Ls] } + end; +handle_nlmsg(RTM=#dellink{family=_Fam,index=Index,flags=_Fs,change=_Cs, + attributes=As}, State) -> + ?debug("RTM = ~p\n", [RTM]), + Name = proplists:get_value(ifname, As, ""), + %% does this delete the link? + case lists:keytake(Index, #link.index, State#state.link_list) of + false -> + ?warning("Warning link index=~w not found", [Index]), + State; + {value,L,Ls} -> + As1 = dict:to_list(L#link.attr), + update_attrs(Name, link, As1, undefined, State#state.sub_list), + State#state { link_list = Ls } + end; +handle_nlmsg(RTM=#newaddr { family=Fam, prefixlen=Prefixlen, + flags=Flags, scope=Scope, + index=Index, attributes=As }, + State) -> + ?debug("RTM = ~p", [RTM]), + Addr = proplists:get_value(address, As, {}), + Name = proplists:get_value(label, As, ""), + As1 = [{family,Fam},{prefixlen,Prefixlen},{flags,Flags}, + {scope,Scope},{index,Index} | As], + case lists:keymember(Index, #link.index, State#state.link_list) of + false -> + ?warning("link index ~p does not exist", [Index]); + true -> + ok + end, + case lists:keytake(Addr, #addr.addr, State#state.addr_list) of + false -> + Attrs = update_attrs(Name,addr,As1,dict:new(),State#state.sub_list), + Y = #addr { addr=Addr, name = Name, index=Index, attr=Attrs }, + Ys = [Y|State#state.addr_list], + State#state { addr_list = Ys }; + {value,Y,Ys} -> + Attr = update_attrs(Name,addr,As1,Y#addr.attr,State#state.sub_list), + Y1 = Y#addr { index=Index, name=Name, attr = Attr }, + State#state { addr_list = [Y1|Ys] } + end; + +handle_nlmsg(RTM=#deladdr { family=_Fam, index=_Index, attributes=As }, + State) -> + ?debug("RTM = ~p", [RTM]), + Addr = proplists:get_value(address, As, {}), + Name = proplists:get_value(label, As, ""), + case lists:keytake(Addr, #addr.addr, State#state.addr_list) of + false -> + ?warning("Warning addr=~s not found", [Addr]), + State; + {value,Y,Ys} -> + As1 = dict:to_list(Y#addr.attr), + update_attrs(Name, addr, As1, undefined, State#state.sub_list), + State#state { addr_list = Ys } + end; +handle_nlmsg(#done { }, State) -> + case State#state.request of + undefined -> + dispatch_command(State); + #request { tmr = Tmr, from = From, reply = Reply } -> + ?debug("handle_nlmsg: DONE: ~p", + [State#state.request]), + erlang:cancel_timer(Tmr), + gen_server:reply(From, Reply), + State1 = State#state { request = undefined }, + dispatch_command(State1) + end; +handle_nlmsg(Err=#error { errno=Err }, State) -> + ?debug("handle_nlmsg: ERROR: ~p", [State#state.request]), + case State#state.request of + undefined -> + dispatch_command(State); + #request { tmr = Tmr, from = From } -> + ?debug("handle_nlmsg: DONE: ~p", + [State#state.request]), + erlang:cancel_timer(Tmr), + %% fixme: convert errno to posix error (netlink.inc?) + gen_server:reply(From, {error,Err}), + State1 = State#state { request = undefined }, + dispatch_command(State1) + end; + +handle_nlmsg(RTM, State) -> + ?debug("netlink: handle_nlmsg, ignore ~p", [RTM]), + State. + +%% update attributes form interface "Name" +%% From to To Type is either link | addr +update_attrs(Name,Type,As,undefined,Subs) -> + lists:foreach( + fun({K,Vold}) -> + send_event(Name,Type,K,Vold,undefined,Subs) + end, As), + undefined; +update_attrs(Name,Type,As,To,Subs) -> + lists:foldl( + fun({K,Vnew},D) -> + case dict:find(K,D) of + error -> + send_event(Name,Type,K,undefined,Vnew,Subs), + dict:store(K,Vnew,D); + {ok,Vnew} -> D; %% already exist + {ok,Vold} -> + send_event(Name,Type,K,Vold,Vnew,Subs), + dict:store(K,Vnew,D) + end + end, To, As). + + +send_event(Name,Type,Field,Old,New,[S|SList]) when + S#subscription.name =:= Name; S#subscription.name =:= "" -> + case S#subscription.fields =:= all orelse + S#subscription.fields =:= Type orelse + lists:member(Field,S#subscription.fields) orelse + lists:member({Type,Field},S#subscription.fields) of + true -> + S#subscription.pid ! {netlink,S#subscription.mon, + Name,Field,Old,New}, + send_event(Name,Type,Field,Old,New,SList); + false -> + send_event(Name,Type,Field,Old,New,SList) + end; +send_event(Name,Type,Field,Old,New,[_|SList]) -> + send_event(Name,Type,Field,Old,New,SList); +send_event(_Name,_Type,_Field,_Old,_New,[]) -> + ok. + + +match(Y,L,[{Field,Value}|Match]) when is_atom(Field) -> + case find2(Field,Y,L) of + {ok,Value} -> match(Y, L, Match); + _ -> false + end; +match(Y,L,[{Op,Field,Value}|Match]) when is_atom(Op),is_atom(Field) -> + case find2(Y,L,Field) of + {ok,FValue} -> + case compare(Op,FValue,Value) of + true -> match(Y,L,Match); + false -> false + end; + error -> + false + end; +match(_Y, _L, []) -> + true. + +find2(Key,D1,D2) -> + case dict:find(Key,D1) of + error -> + dict:find(Key,D2); + Res -> Res + end. + + +format_link(L) -> + dict:fold( + fun(af_spec,_V,A) -> A; + (map,_V,A) -> A; + (stats,_V,A) -> A; + (stats64,_V,A) -> A; + (change,_V,A) -> A; + (K,V,A) -> + [["\n ",name_to_list(K), " ",value_to_list(K,V),";"]|A] + end, [], L#link.attr). + +format_addr(Y) -> + ["\n", " addr {", + dict:fold( + fun(cacheinfo,_V,A) -> A; + (K,V,A) -> + [[" ",name_to_list(K), " ",value_to_list(K,V),";"]|A] + end, [], Y#addr.attr), "}"]. + +name_to_list(K) when is_atom(K) -> + atom_to_list(K); +name_to_list(K) when is_integer(K) -> + integer_to_list(K). + + +value_to_list(local,V) -> format_a(V); +value_to_list(address,V) -> format_a(V); +value_to_list(broadcast,V) -> format_a(V); +value_to_list(multicast,V) -> format_a(V); +value_to_list(anycast,V) -> format_a(V); +value_to_list(_, V) -> io_lib:format("~p", [V]). + +format_a(undefined) -> ""; +format_a(A) when is_tuple(A), tuple_size(A) =:= 6 -> + io_lib:format("~2.16.0b:~2.16.0b:~2.16.0b:~2.16.0b:~2.16.0b:~2.16.0b", + tuple_to_list(A)); +format_a(A) when is_tuple(A), tuple_size(A) =:= 4 -> + inet_parse:ntoa(A); +format_a(A) when is_tuple(A), tuple_size(A) =:= 8 -> + inet_parse:ntoa(A). + +compare('==',A,B) -> A == B; +compare('=:=',A,B) -> A =:= B; +compare('<' ,A,B) -> A < B; +compare('=<' ,A,B) -> A =< B; +compare('>' ,A,B) -> A > B; +compare('>=' ,A,B) -> A >= B; +compare('/=' ,A,B) -> A /= B; +compare('=/=' ,A,B) -> A =/= B; +compare(_,_,_) -> false. diff --git a/deps/netlink/src/netlink.hrl b/deps/netlink/src/netlink.hrl new file mode 100644 index 0000000..e03da66 --- /dev/null +++ b/deps/netlink/src/netlink.hrl @@ -0,0 +1,64 @@ + +%% netlink protocols +-define(NETLINK_ROUTE, 0). %% Routing/device hook +-define(NETLINK_UNUSED, 1). %% Unused number +-define(NETLINK_USERSOCK, 2). %% Reserved for user mode socket protocols +-define(NETLINK_FIREWALL, 3). %% Unused number, formerly ip_queue +-define(NETLINK_SOCK_DIAG, 4). %% socket monitoring +-define(NETLINK_NFLOG, 5). %% netfilter/iptables ULOG */ +-define(NETLINK_XFRM, 6). %% ipsec */ +-define(NETLINK_SELINUX, 7). %% SELinux event notifications */ +-define(NETLINK_ISCSI, 8). %% Open-iSCSI */ +-define(NETLINK_AUDIT, 9). %% auditing */ +-define(NETLINK_FIB_LOOKUP, 10). +-define(NETLINK_CONNECTOR, 11). +-define(NETLINK_NETFILTER, 12). %% netfilter subsystem +-define(NETLINK_IP6_FW, 13). +-define(NETLINK_DNRTMSG, 14). %% DECnet routing messages +-define(NETLINK_KOBJECT_UEVENT, 15). %% Kernel messages to userspace +-define(NETLINK_GENERIC, 16). +%% leave room for NETLINK_DM (DM Events) +-define(NETLINK_SCSITRANSPORT, 18). %% SCSI Transports +-define(NETLINK_ECRYPTFS, 19). +-define(NETLINK_RDMA, 20). +-define(NETLINK_CRYPTO, 21). %% Crypto layer */ +-define(NETLINK_INET_DIAG, ?NETLINK_SOCK_DIAG). + +-define(NFNLGRP_NONE, 0). +-define(NFNLGRP_CONNTRACK_NEW, 1). +-define(NFNLGRP_CONNTRACK_UPDATE, 2). +-define(NFNLGRP_CONNTRACK_DESTROY, 3). +-define(NFNLGRP_CONNTRACK_EXP_NEW, 4). +-define(NFNLGRP_CONNTRACK_EXP_UPDATE, 5). +-define(NFNLGRP_CONNTRACK_EXP_DESTROY, 6). + +-define(RTNLGRP_NONE, 0). +-define(RTNLGRP_LINK, 1). +-define(RTNLGRP_NOTIFY, 2). +-define(RTNLGRP_NEIGH, 3). +-define(RTNLGRP_TC, 4). +-define(RTNLGRP_IPV4_IFADDR, 5). +-define(RTNLGRP_IPV4_MROUTE, 6). +-define(RTNLGRP_IPV4_ROUTE, 7). +-define(RTNLGRP_IPV4_RULE, 8). +-define(RTNLGRP_IPV6_IFADDR, 9). +-define(RTNLGRP_IPV6_MROUTE, 10). +-define(RTNLGRP_IPV6_ROUTE, 11). +-define(RTNLGRP_IPV6_IFINFO, 12). +-define(RTNLGRP_DECnet_IFADDR, 13). +-define(RTNLGRP_NOP2, 14). +-define(RTNLGRP_DECnet_ROUTE, 15). +-define(RTNLGRP_DECnet_RULE, 16). +-define(RTNLGRP_NOP4, 17). +-define(RTNLGRP_IPV6_PREFIX, 18). +-define(RTNLGRP_IPV6_RULE, 19). +-define(RTNLGRP_ND_USEROPT, 20). +-define(RTNLGRP_PHONET_IFADDR, 21). +-define(RTNLGRP_PHONET_ROUTE, 22). +-define(RTNLGRL_DCB, 23). + +-record(nlmsg, + { + hdr, + data + }). diff --git a/deps/netlink/src/netlink.inc b/deps/netlink/src/netlink.inc new file mode 100644 index 0000000..3d76d8d --- /dev/null +++ b/deps/netlink/src/netlink.inc @@ -0,0 +1,981 @@ +%% -*- erlang -*- +%% +%% nlink data definitions +%% +{define, 'NLMSG_NOOP', 1}. +{define, 'NLMSG_ERROR', 2}. +{define, 'NLMSG_DONE', 3}. +{define, 'NLMSG_OVERRUN', 4}. + +{define, 'RTM_NEWLINK', 16}. +{define, 'RTM_DELLINK', 17}. +{define, 'RTM_GETLINK', 18}. +{define, 'RTM_SETLINK', 19}. +{define, 'RTM_NEWADDR', 20}. +{define, 'RTM_DELADDR', 21}. +{define, 'RTM_GETADDR', 22}. +{define, 'RTM_NEWROUTE', 24}. +{define, 'RTM_DELROUTE', 25}. +{define, 'RTM_GETROUTE', 26}. +{define, 'RTM_NEWNEIGH', 28}. +{define, 'RTM_DELNEIGH', 29}. +{define, 'RTM_GETNEIGH', 30}. +{define, 'RTM_NEWRULE', 32}. +{define, 'RTM_DELRULE', 33}. +{define, 'RTM_GETRULE', 34}. +{define, 'RTM_NEWQDISC', 36}. +{define, 'RTM_DELQDISC', 37}. +{define, 'RTM_GETQDISC', 38}. +{define, 'RTM_NEWTCLASS', 40}. +{define, 'RTM_DELTCLASS', 41}. +{define, 'RTM_GETTCLASS', 42}. +{define, 'RTM_NEWTFILTER', 44}. +{define, 'RTM_DELTFILTER', 45}. +{define, 'RTM_GETTFILTER', 46}. +{define, 'RTM_NEWACTION', 48}. +{define, 'RTM_DELACTION', 49}. +{define, 'RTM_GETACTION', 50}. +{define, 'RTM_NEWPREFIX', 52}. +{define, 'RTM_GETMULTICAST', 58}. +{define, 'RTM_GETANYCAST', 62}. +{define, 'RTM_NEWNEIGHTBL', 64}. +{define, 'RTM_GETNEIGHTBL', 66}. +{define, 'RTM_SETNEIGHTBL', 67}. +{define, 'RTM_NEWNDUSEROPT', 68}. +{define, 'RTM_NEWADDRLABEL', 72}. +{define, 'RTM_DELADDRLABEL', 73}. +{define, 'RTM_GETADDRLABEL', 74}. +{define, 'RTM_GETDCB', 78}. +{define, 'RTM_SETDCB', 79}. + +{define, 'AF_UNSPEC', 0}. +{define, 'AF_LOCAL', 1}. +{define, 'AF_UNIX', 1}. +{define, 'AF_FILE', 1}. +{define, 'AF_INET', 2}. +{define, 'AF_AX25', 3}. +{define, 'AF_IPX', 4}. +{define, 'AF_APPLETALK', 5}. +{define, 'AF_NETROM', 6}. +{define, 'AF_BRIDGE', 7}. +{define, 'AF_ATMPVC', 8}. +{define, 'AF_X25', 9}. +{define, 'AF_INET6', 10}. +{define, 'AF_ROSE', 11}. +{define, 'AF_DECNET', 12}. +{define, 'AF_NETBEUI', 13}. +{define, 'AF_SECURITY', 14}. +{define, 'AF_KEY', 15}. +{define, 'AF_NETLINK', 16}. +{define, 'AF_ROUTE', 16}. +{define, 'AF_PACKET', 17}. +{define, 'AF_ASH', 18}. +{define, 'AF_ECONET', 19}. +{define, 'AF_ATMSVC', 20}. +{define, 'AF_RDS', 21}. +{define, 'AF_SNA', 22}. +{define, 'AF_IRDA', 23}. +{define, 'AF_PPPOX', 24}. +{define, 'AF_WANPIPE', 25}. +{define, 'AF_LLC', 26}. +{define, 'AF_CAN', 29}. +{define, 'AF_TIPC', 30}. +{define, 'AF_BLUETOOTH', 31}. +{define, 'AF_IUCV', 32}. +{define, 'AF_RXRPC', 33}. +{define, 'AF_ISDN', 34}. +{define, 'AF_PHONET', 35}. +{define, 'AF_IEEE802154', 36}. + +{define, 'PROTO_IP', 0}. +{define, 'PROTO_ICMP', 1}. +{define, 'PROTO_IGMP', 2}. +{define, 'PROTO_IPIP', 4}. +{define, 'PROTO_TCP', 6}. +{define, 'PROTO_EGP', 8}. +{define, 'PROTO_PUP', 12}. +{define, 'PROTO_UDP', 17}. +{define, 'PROTO_IDP', 22}. +{define, 'PROTO_TP', 29}. +{define, 'PROTO_DCCP', 33}. +{define, 'PROTO_IPV6', 41}. +{define, 'PROTO_ROUTING', 43}. +{define, 'PROTO_FRAGMENT', 44}. +{define, 'PROTO_RSVP', 46}. +{define, 'PROTO_GRE', 47}. +{define, 'PROTO_ESP', 50}. +{define, 'PROTO_AH', 51}. +{define, 'PROTO_ICMPV6', 58}. +{define, 'PROTO_NONE', 59}. +{define, 'PROTO_DSTOPTS', 60}. +{define, 'PROTO_MTP', 92}. +{define, 'PROTO_ENCAP', 98}. +{define, 'PROTO_PIM', 103}. +{define, 'PROTO_COMP', 108}. +{define, 'PROTO_SCTP', 132}. +{define, 'PROTO_UDPLITE', 136}. +{define, 'PROTO_RAW', 255}. + +{define, 'ARPHRD_NETROM', 0}. %% from KA9Q: NET/ROM pseudo +{define, 'ARPHRD_ETHER ', 1}. %% Ethernet 10Mbps +{define, 'ARPHRD_EETHER', 2}. %% Experimental Ethernet +{define, 'ARPHRD_AX25', 3}. %% AX.25 Level 2 +{define, 'ARPHRD_PRONET', 4}. %% PROnet token ring +{define, 'ARPHRD_CHAOS', 5}. %% Chaosnet +{define, 'ARPHRD_IEEE802',6}. %% IEEE 802.2 Ethernet/TR/TB +{define, 'ARPHRD_ARCNET', 7}. %% ARCnet +{define, 'ARPHRD_APPLETLK', 8}. %% APPLEtalk +{define, 'ARPHRD_DLCI', 15}. %% Frame Relay DLCI +{define, 'ARPHRD_ATM', 19}. %% ATM +{define, 'ARPHRD_METRICOM', 23}. %% Metricom STRIP (new IANA id) +{define, 'ARPHRD_IEEE1394', 24}. %% IEEE 1394 IPv4 - RFC 2734 +{define, 'ARPHRD_EUI64', 27}. %% EUI-64 +{define, 'ARPHRD_INFINIBAND', 32}. %% InfiniBand +%% Dummy types for non ARP hardware +{define, 'ARPHRD_SLIP', 256}. +{define, 'ARPHRD_CSLIP', 257}. +{define, 'ARPHRD_SLIP6', 258}. +{define, 'ARPHRD_CSLIP6', 259}. +{define, 'ARPHRD_RSRVD', 260}. %% Notional KISS type +{define, 'ARPHRD_ADAPT', 264}. +{define, 'ARPHRD_ROSE', 270}. +{define, 'ARPHRD_X25', 271}. %% CCITT X.25 +{define, 'ARPHRD_HWX25', 272}. %% Boards with X.25 in firmware +{define, 'ARPHRD_CAN', 280}. %% Controller Area Network +{define, 'ARPHRD_PPP', 512}. +{define, 'ARPHRD_CISCO', 513}. %% Cisco HDLC +{define, 'ARPHRD_HDLC', 513}. +{define, 'ARPHRD_LAPB', 516}. %% LAPB +{define, 'ARPHRD_DDCMP', 517}. %% Digitals DDCMP protocol +{define, 'ARPHRD_RAWHDLC', 518}. %% Raw HDLC +{define, 'ARPHRD_TUNNEL', 768}. %% IPIP tunnel +{define, 'ARPHRD_TUNNEL6', 769}. %% IP6IP6 tunnel +{define, 'ARPHRD_FRAD', 770}. %% Frame Relay Access Device +{define, 'ARPHRD_SKIP', 771}. %% SKIP vif +{define, 'ARPHRD_LOOPBACK', 772}. %% Loopback device +{define, 'ARPHRD_LOCALTLK', 773}. %% Localtalk device +{define, 'ARPHRD_FDDI', 774}. %% Fiber Distributed Data Interface +{define, 'ARPHRD_BIF', 775}. %% AP1000 BIF +{define, 'ARPHRD_SIT', 776}. %% sit0 device - IPv6-in-IPv4 +{define, 'ARPHRD_IPDDP', 777}. %% IP over DDP tunneller +{define, 'ARPHRD_IPGRE', 778}. %% GRE over IP +{define, 'ARPHRD_PIMREG', 779}. %% PIMSM register interface +{define, 'ARPHRD_HIPPI', 780}. %% High Performance Parallel Interface +{define, 'ARPHRD_ASH', 781}. %% Nexus 64Mbps Ash +{define, 'ARPHRD_ECONET', 782}. %% Acorn Econet +{define, 'ARPHRD_IRDA', 783}. %% Linux-IrDA +%% ARP works differently on different FC media .. so +{define, 'ARPHRD_FCPP', 784}. %% Point to point fibrechannel +{define, 'ARPHRD_FCAL', 785}. %% Fibrechannel arbitrated loop +{define, 'ARPHRD_FCPL', 786}. %% Fibrechannel public loop +{define, 'ARPHRD_FCFABRIC', 787}. %% Fibrechannel fabric + %% 787->799 reserved for fibrechannel media types +{define, 'ARPHRD_IEEE802_TR', 800}. %% Magic type ident for TR +{define, 'ARPHRD_IEEE80211', 801}. %% IEEE 802.11 +{define, 'ARPHRD_IEEE80211_PRISM', 802}. %% IEEE 802.11 + Prism2 header +{define, 'ARPHRD_IEEE80211_RADIOTAP', 803}. %% IEEE 802.11 + radiotap header +{define, 'ARPHRD_IEEE802154', 804}. +{define, 'ARPHRD_PHONET', 820}. %% PhoNet media type +{define, 'ARPHRD_PHONET_PIPE', 821}. %% PhoNet pipe header +{define, 'ARPHRD_CAIF', 822}. %% CAIF media type +{define, 'ARPHRD_VOID', 65535}. %% Void type, nothing is known +{define, 'ARPHRD_NONE', 65534}. %% zero header length + +{enum, family, + [ + {unspec, 'AF_UNSPEC'}, + {local, 'AF_LOCAL'}, + {inet, 'AF_INET'}, + {ax25, 'AF_AX25'}, + {ipx, 'AF_IPX'}, + {appletalk, 'AF_APPLETALK'}, + {netrom, 'AF_NETROM'}, + {bridge, 'AF_BRIDGE'}, + {atmpvc, 'AF_ATMPVC'}, + {x25, 'AF_X25'}, + {inet6, 'AF_INET6'}, + {rose, 'AF_ROSE'}, + {decnet, 'AF_DECNET'}, + {netbeui, 'AF_NETBEUI'}, + {security, 'AF_SECURITY'}, + {key, 'AF_KEY'}, + {netlink, 'AF_NETLINK'}, + {packet, 'AF_PACKET'}, + {ash, 'AF_ASH'}, + {econet, 'AF_ECONET'}, + {atmsvc, 'AF_ATMSVC'}, + {rds, 'AF_RDS'}, + {sna, 'AF_SNA'}, + {irda, 'AF_IRDA'}, + {pppox, 'AF_PPPOX'}, + {wanpipe, 'AF_WANPIPE'}, + {llc, 'AF_LLC'}, + {can, 'AF_CAN'}, + {tipc, 'AF_TIPC'}, + {bluetooth, 'AF_BLUETOOTH'}, + {iucv, 'AF_IUCV'}, + {rxrpc, 'AF_RXRPC'}, + {isdn, 'AF_ISDN'}, + {phonet, 'AF_PHONET'}, + {ieee802154, 'AF_IEEE802154'} +]}. + +{enum, protocol, + [ + {ip, 'PROTO_IP'}, + {icmp, 'PROTO_ICMP'}, + {igmp, 'PROTO_IGMP'}, + {ipip, 'PROTO_IPIP'}, + {tcp, 'PROTO_TCP'}, + {egp, 'PROTO_EGP'}, + {pup, 'PROTO_PUP'}, + {udp, 'PROTO_UDP'}, + {idp, 'PROTO_IDP'}, + {tp, 'PROTO_TP'}, + {dccp, 'PROTO_DCCP'}, + {ipv6, 'PROTO_IPV6'}, + {routing, 'PROTO_ROUTING'}, + {fragment, 'PROTO_FRAGMENT'}, + {rsvp, 'PROTO_RSVP'}, + {gre, 'PROTO_GRE'}, + {esp, 'PROTO_ESP'}, + {ah, 'PROTO_AH'}, + {icmpv6, 'PROTO_ICMPV6'}, + {none, 'PROTO_NONE'}, + {dstopts, 'PROTO_DSTOPTS'}, + {mtp, 'PROTO_MTP'}, + {encap, 'PROTO_ENCAP'}, + {pim, 'PROTO_PIM'}, + {comp, 'PROTO_COMP'}, + {sctp, 'PROTO_SCTP'}, + {udplite, 'PROTO_UDPLITE'}, + {raw, 'PROTO_RAW'} +]}. + +{enum, arphrd, + [ + {netrom, 'ARPHRD_NETROM'}, + {ether , 'ARPHRD_ETHER '}, + {eether, 'ARPHRD_EETHER'}, + {ax25, 'ARPHRD_AX25'}, + {pronet, 'ARPHRD_PRONET'}, + {chaos, 'ARPHRD_CHAOS'}, + {ieee802, 'ARPHRD_IEEE802'}, + {arcnet, 'ARPHRD_ARCNET'}, + {appletlk, 'ARPHRD_APPLETLK'}, + {dlci, 'ARPHRD_DLCI'}, + {atm, 'ARPHRD_ATM'}, + {metricom, 'ARPHRD_METRICOM'}, + {ieee1394, 'ARPHRD_IEEE1394'}, + {eui64, 'ARPHRD_EUI64'}, + {infiniband, 'ARPHRD_INFINIBAND'}, + {slip, 'ARPHRD_SLIP'}, + {cslip, 'ARPHRD_CSLIP'}, + {slip6, 'ARPHRD_SLIP6'}, + {cslip6, 'ARPHRD_CSLIP6'}, + {rsrvd, 'ARPHRD_RSRVD'}, + {adapt, 'ARPHRD_ADAPT'}, + {rose, 'ARPHRD_ROSE'}, + {x25, 'ARPHRD_X25'}, + {hwx25, 'ARPHRD_HWX25'}, + {can, 'ARPHRD_CAN'}, + {ppp, 'ARPHRD_PPP'}, + {hdlc, 'ARPHRD_HDLC'}, + {lapb, 'ARPHRD_LAPB'}, + {ddcmp, 'ARPHRD_DDCMP'}, + {rawhdlc, 'ARPHRD_RAWHDLC'}, + {tunnel, 'ARPHRD_TUNNEL'}, + {tunnel6, 'ARPHRD_TUNNEL6'}, + {frad, 'ARPHRD_FRAD'}, + {skip, 'ARPHRD_SKIP'}, + {loopback, 'ARPHRD_LOOPBACK'}, + {localtlk, 'ARPHRD_LOCALTLK'}, + {fddi, 'ARPHRD_FDDI'}, + {bif, 'ARPHRD_BIF'}, + {sit, 'ARPHRD_SIT'}, + {ipddp, 'ARPHRD_IPDDP'}, + {ipgre, 'ARPHRD_IPGRE'}, + {pimreg, 'ARPHRD_PIMREG'}, + {hippi, 'ARPHRD_HIPPI'}, + {ash, 'ARPHRD_ASH'}, + {econet, 'ARPHRD_ECONET'}, + {irda, 'ARPHRD_IRDA'}, + {fcpp, 'ARPHRD_FCPP'}, + {fcal, 'ARPHRD_FCAL'}, + {fcpl, 'ARPHRD_FCPL'}, + {fcfabric, 'ARPHRD_FCFABRIC'}, + {ieee802_tr, 'ARPHRD_IEEE802_TR'}, + {ieee80211, 'ARPHRD_IEEE80211'}, + {ieee80211_prism, 'ARPHRD_IEEE80211_PRISM'}, + {ieee80211_radiotap, 'ARPHRD_IEEE80211_RADIOTAP'}, + {ieee802154, 'ARPHRD_IEEE802154'}, + {phonet, 'ARPHRD_PHONET'}, + {phonet_pipe, 'ARPHRD_PHONET_PIPE'}, + {caif, 'ARPHRD_CAIF'}, + {void, 'ARPHRD_VOID'}, + {none, 'ARPHRD_NONE'} +]}. + + +{enum, nlmsg_type, + [ + {noop, 'NLMSG_NOOP'}, + {error, 'NLMSG_ERROR'}, + {done, 'NLMSG_DONE'}, + {overrun, 'NLMSG_OVERRUN'}, + {newlink, 'RTM_NEWLINK'}, + {dellink, 'RTM_DELLINK'}, + {getlink, 'RTM_GETLINK'}, + {setlink, 'RTM_SETLINK'}, + {newaddr, 'RTM_NEWADDR'}, + {deladdr, 'RTM_DELADDR'}, + {getaddr, 'RTM_GETADDR'}, + {newroute, 'RTM_NEWROUTE'}, + {delroute, 'RTM_DELROUTE'}, + {getroute, 'RTM_GETROUTE'}, + {newneigh, 'RTM_NEWNEIGH'}, + {delneigh, 'RTM_DELNEIGH'}, + {getneigh, 'RTM_GETNEIGH'}, + {newrule, 'RTM_NEWRULE'}, + {delrule, 'RTM_DELRULE'}, + {getrule, 'RTM_GETRULE'}, + {newqdisc, 'RTM_NEWQDISC'}, + {delqdisc, 'RTM_DELQDISC'}, + {getqdisc, 'RTM_GETQDISC'}, + {newtclass, 'RTM_NEWTCLASS'}, + {deltclass, 'RTM_DELTCLASS'}, + {gettclass, 'RTM_GETTCLASS'}, + {newtfilter, 'RTM_NEWTFILTER'}, + {deltfilter, 'RTM_DELTFILTER'}, + {gettfilter, 'RTM_GETTFILTER'}, + {newaction, 'RTM_NEWACTION'}, + {delaction, 'RTM_DELACTION'}, + {getaction, 'RTM_GETACTION'}, + {newprefix, 'RTM_NEWPREFIX'}, + {getmulticast, 'RTM_GETMULTICAST'}, + {getanycast, 'RTM_GETANYCAST'}, + {newneightbl, 'RTM_NEWNEIGHTBL'}, + {getneightbl, 'RTM_GETNEIGHTBL'}, + {setneightbl, 'RTM_SETNEIGHTBL'}, + {newnduseropt, 'RTM_NEWNDUSEROPT'}, + {newaddrlabel, 'RTM_NEWADDRLABEL'}, + {deladdrlabel, 'RTM_DELADDRLABEL'}, + {getaddrlabel, 'RTM_GETADDRLABEL'}, + {getdcb, 'RTM_GETDCB'}, + {setdcb, 'RTM_SETDCB'} + ]}. + +%% enumeration of flag numbers (up=0, broadcast=1 ...) +%% used as flag then up = (1 << 0) broadcast = (1 << 1) +{enum, iff_flags, + [ + up, + broadcast, + debug, + loopback, + pointopoint, + notrailers, + running, + noarp, + promisc, + allmulti, + master, + slave, + multicast, + portsel, + automedia, + ynamic, + lower_up, + dormant, + echo + ]}. + +{enum, nlm_flags, + [ + {request, 0}, + {multi, 1}, + {ack, 2}, + {echo, 3} + ]}. + +{enum, nlm_get_flags, + [ + {request, 0}, + {multi, 1}, + {ack, 2}, + {echo, 3}, + {root, 8}, + {match, 9}, + {atomic, 10} + ]}. + +{enum, nlm_new_flags, + [ + {request, 0}, + {multi, 1}, + {ack, 2}, + {echo, 3}, + {replace, 8}, + {excl, 9}, + {create, 10}, + {append, 11} + ]}. + +{define, 'IPCTNL_MSG_CT_NEW', 0}. +{define, 'IPCTNL_MSG_CT_GET', 1}. +{define, 'IPCTNL_MSG_CT_DELETE', 2}. +{define, 'IPCTNL_MSG_CT_GET_CTRZERO', 3}. + +{enum, ctm_msgtype_netlink, + [ + {noop, 'NLMSG_NOOP'}, + {error, 'NLMSG_ERROR'}, + {done, 'NLMSG_DONE'}, + {overrun, 'NLMSG_OVERRUN'} + ]}. + +{define, 'IPCTNL_MSG_EXP_NEW', 0}. +{define, 'IPCTNL_MSG_EXP_GET', 1}. +{define, 'IPCTNL_MSG_EXP_DELETE', 2}. + +{enum, ctm_msgtype_ctnetlink, + [ + {new, 'IPCTNL_MSG_CT_NEW'}, + {get, 'IPCTNL_MSG_CT_GET'}, + {delete, 'IPCTNL_MSG_CT_DELETE'}, + {get_ctrzero, 'IPCTNL_MSG_CT_GET_CTRZERO'} + ]}. + +{enum, ctm_msgtype_ctnetlink_exp, + [ + {new, 'IPCTNL_MSG_EXP_NEW'}, + {get, 'IPCTNL_MSG_EXP_GET'}, + {delete, 'IPCTNL_MSG_EXP_DELETE'} + ]}. + +{attribute, ctnetlink_tuple_ip, + [ + {unspec, binary_t}, + {v4_src, ipv4_addr_t}, + {v4_dst, ipv4_addr_t}, + {v6_src, ipv6_addr_t}, + {v6_dst, ipv6_addr_t} + ]}. + +{attribute, ctnetlink_tuple_proto, + [ + {unspec, binary_t}, + {num, {enum,uint8_t,protocol}}, + {src_port, uint16_t}, + {dst_port, uint16_t}, + {icmp_id, uint16_t}, + {icmp_type, uint8_t}, + {icmp_code, uint8_t}, + {icmpv6_id, binary_t}, + {icmpv6_type, binary_t}, + {icmpv6_code, binary_t} + ]}. + +{attribute, ctnetlink_tuple, + [ + {unspec, binary_t}, + {ip, ctnetlink_tuple_ip}, + {proto, ctnetlink_tuple_proto} + ]}. + +{attribute, ctnetlink_nat_seq_adj, + [ + {unspec, binary_t}, + {correction_pos, uint32_t}, + {offset_before, uint32_t}, + {offset_after, uint32_t} + ]}. + +{enum, ctnetlink_protoinfo_tcp_state, + [ + none, + syn_sent, + syn_recv, + established, + fin_wait, + close_wait, + last_ack, + time_wait, + close, + listen, + max, + ignore + ]}. + +{attribute, ctnetlink_protoinfo_tcp, + [ + {unspec, binary_t}, + {state, {enum,uint8_t,ctnetlink_protoinfo_tcp_state}}, + {wscale_original, uint8_t}, + {wscale_reply, uint8_t}, + {flags_original, uint16_t}, + {flags_reply, uint16_t} + ]}. + + +{attribute, ctnetlink_protoinfo, + [ + {unspec, binary_t}, + {tcp, ctnetlink_protoinfo_tcp}, + {dccp, binary_t}, %% ctnetlink_protoinfo_dccp}, + {sctp, binary_t} %% ctnetlink_protoinfo_sctp} + ]}. + +{enum, ctnetlink_status, + [ + expected, + seen_reply, + assured, + confirmed, + src_nat, + dst_nat, + seq_adjust, + src_nat_done, + dst_nat_done, + dying, + fixed_timeout + ]}. + +{attribute, ctnetlink_help, + [ + {unspec, binary_t}, + {name, string_t} + ]}. + +{attribute, ctnetlink_counters, + [ + {unspec, binary_t}, + {packets, uint64_t}, + {bytes, uint64_t}, + {packets32, uint32_t}, + {bytes32, uint32_t} + ]}. + +{attribute, ctnetlink_timestamp, + [ + {unspec, binary_t}, + {start, uint64_t}, + {stop, uint64_t} + ]}. + +{attribute, ctnetlink_exp_tuple_ip, + [ + {unspec, binary_t}, + {v4_src, ipv4_addr_t}, + {v4_dst, ipv4_addr_t}, + {v6_src, ipv6_addr_t}, + {v6_dst, ipv6_addr_t} + ]}. + +{attribute, ctnetlink_exp_tuple_proto, + [ + {unspec, binary_t}, + {num, {enum,uint8_t,protocol}}, + {src_port, uint16_t}, + {dst_port, uint16_t}, + {icmp_id, uint16_t}, + {icmp_type, uint8_t}, + {icmp_code, uint8_t}, + {icmpv6_id, binary_t}, + {icmpv6_type, binary_t}, + {icmpv6_code, binary_t} + ]}. + +{attribute, ctnetlink_exp_tuple, + [ + {unspec, binary_t}, + {ip, ctnetlink_exp_tuple_ip}, + {proto, ctnetlink_exp_tuple_proto} + ]}. + +{enum, ctnetlink_exp_flags, + [ + permanent, + inactive, + userspace + ]}. + + +{attribute, ctnetlink_exp, + [ + {unspec, binary_t}, + {master, ctnetlink_exp_tuple}, + {tuple, ctnetlink_exp_tuple}, + {mask, ctnetlink_exp_tuple}, + {timeout, uint32_t}, + {id, uint32_t}, + {help_name, string_t}, + {zone, uint16_t}, + {flags, {flags,uint32_t,ctnetlink_exp_flags}} + ]}. + + +{attribute, ctnetlink, + [ + {unspec, binary_t}, + {tuple_orig, ctnetlink_tuple}, + {tuple_reply, ctnetlink_tuple}, + {status, {flags,uint32_t,ctnetlink_status}}, + {protoinfo, ctnetlink_protoinfo}, + {help, ctnetlink_help}, + {nat_src, binary_t}, + {timeout, uint32_t}, + {mark, uint32_t}, + {counters_orig, ctnetlink_counters}, + {counters_reply, ctnetlink_counters}, + {use, uint32_t}, + {id, uint32_t}, + {nat_dst, binary_t}, + {tuple_master, ctnetlink_tuple}, + {nat_seq_adj_orig, ctnetlink_nat_seq_adj}, + {nat_seq_adj_reply, ctnetlink_nat_seq_adj}, + {secmark, uint32_t}, + {zone, uint16_t}, + {secctx, binary_t}, + {timestamp, ctnetlink_timestamp} + ]}. + + +{attribute, rtnetlink_neigh, + [ + {unspec, binary_t}, + {dst, addr_t}, + {lladdr, ether_addr_t}, + {cacheinfo, {array,uint32_t}}, + {probes, uint32_t} + ]}. + +{enum, rtnetlink_rtm_type, + [ + unspec, + unicast, + local, + broadcast, + anycast, + multicast, + blackhole, + unreachable, + prohibit, + throw, + nat, + xresolve + ]}. + +{enum, rtnetlink_rtm_protocol, + [ + {unspec, 0}, + {redirect, 1}, + {kernel, 2}, + {boot, 3}, + {static, 4}, + {gated, 8}, + {ra, 9}, + {mrt, 10}, + {zebra, 11}, + {bird, 12}, + {dnrouted, 13}, + {xorp, 14}, + {ntk, 15}, + {dhcp, 16} + ]}. + +{enum, rtnetlink_rtm_scope, + [ + {universe, 0}, + {site, 200}, + {link, 253}, + {host, 254}, + {nowhere, 255} + ]}. + +%% FIXME: should be bit number? +{enum, rtnetlink_rtm_flags, + [ + {notify, 16#100}, + {cloned, 16#200}, + {equalize, 16#400}, + {prefix, 16#800} + ]}. + +{enum, rtnetlink_rtm_table, + [ + {unspec, 0}, + {compat, 252}, + {default, 253}, + {main, 254}, + {local, 255} + ]}. + +{attribute, rtnetlink_route_metrics, + [ + {unspec, binary_t}, + {lock, uint32_t}, + {mtu, uint32_t}, + {window, uint32_t}, + {rtt, uint32_t}, + {rttvar, uint32_t}, + {ssthresh, uint32_t}, + {cwnd, uint32_t}, + {advmss, uint32_t}, + {reordering, uint32_t}, + {hoplimit, uint32_t}, + {initcwnd, uint32_t}, + {features, uint32_t}, + {rto_min, uint32_t}, + {initrwnd, uint32_t} + ]}. + +{attribute, rtnetlink_addr, + [ + {unspec, binary_t}, + {address, addr_t}, + {local, addr_t}, + {label, string_t}, + {broadcast, addr_t}, + {anycast, addr_t}, + {cacheinfo, {array,uint32_t}}, + {multicast, addr_t} + ]}. + +{enum, rtnetlink_link_operstate, + [ + unknown, + notpresent, + down, + lowerlayerdown, + testing, + dormant, + up + ]}. + +{enum, rtnetlink_link_linkmode, + [ + default, + dormant + ]}. + +{record, if_map, + [ + {memstart, uint64_t}, + {memend, uint64_t}, + {baseaddr, uint64_t}, + {irq, uint16_t}, + {dma, uint8_t}, + {port, uint8_t} + %% fixme: 64 padding? on 64 bit machine? + ]}. + +{attribute, rtnetlink_route, + [ + {unspec, binary_t}, + {dst, addr_t}, + {src, addr_t}, + {iif, uint32_t}, + {oif, uint32_t}, + {gateway, addr_t}, + {priority, uint32_t}, + {prefsrc, addr_t}, + {metrics, {tlvs,rtnetlink_route_metrics}}, + {multipath, binary_t}, + {protoinfo, binary_t}, + {flow, uint32_t}, + {cacheinfo, {array,uint32_t}}, + {session, binary_t}, + {mp_algo, binary_t}, + {table, uint32_t} + ]}. + +{attribute, rtnetlink_link_linkinfo, + [ + {unspec, binary_t}, + {kind, string_t}, + {data, binary_t}, + {xstats, binary_t} + ]}. + +%% inet6? +{enum, rtnetlink_link_protinfo_flags, + [ + {rs_sent, 4}, + {ra_rcvd, 5}, + {ra_managed, 6}, + {ra_othercon, 7}, + {ready, 31} + ]}. + +%% inet6? +{attribute, rtnetlink_link_protinfo, + [ + {unspec, binary_t}, + {flags, {flags,uint32_t,rtnetlink_link_protinfo_flags}}, + {conf, {array,int32_t}}, + {stats, {array,uint64_t}}, + {mcast, binary_t}, + {cacheinfo, {array,uint32_t}}, + {icmp6stats, {array,uint64_t}} + ]}. + + +{attribute, rtnetlink_link, + [ + {unspec, binary_t}, + {address, ether_addr_t}, + {broadcast, ether_addr_t}, + {ifname, string_t}, + {mtu, uint32_t}, + {link, uint32_t}, + {qdisc, string_t}, + {stats, {array,uint32_t}}, + {cost, binary_t}, + {priority, binary_t}, + {master, binary_t}, + {wireless, binary_t}, + {protinfo, {tlvs,rtnetlink_link_protinfo}}, + {txqlen, uint32_t}, + {map, if_map}, + {weight, binary_t}, + {operstate, {enum,uint8_t,rtnetlink_link_operstate}}, + {linkmode, {enum,uint8_t,rtnetlink_link_linkmode}}, + {linkinfo, {tlvs,rtnetlink_link_linkinfo}}, + {net_ns_pid, binary_t}, + {ifalias, string_t}, + {num_vf, uint32_t}, + {vfinfo_list, binary_t}, + {stats64, {array,uint64_t}}, + {vf_ports, binary_t}, + {port_self, binary_t}, + {af_spec, binary_t}, + {group, uint32_t}, %% Group the device belongs to + {net_ns_fd, binary_t}, + {ext_mask, binary_t}, %% Extended info mask, VFs, etc + {promiscuity, uint32_t} %% Promiscuity count: > 0 means acts PROMISC + + ] }. + +{attribute, rtnetlink_prefix, + [ + {unspec, binary_t}, + {address, addr_t}, + {cacheinfo, {array,uint32_t}} %% fixme: add struct rta_cacheinfo + ]}. + +{enum, ifa_flags, + [ + secondary, + nodad, + optimistic, + dadfailed, + homeaddress, + deprecated, + tentative, + permanent + ]}. + +{record, nlmsghdr, + [ + {len, uint32_t}, + {type, uint16_t}, + {flags, uint16_t}, + {seq, uint32_t}, + {pid, uint32_t} + ]}. + +{record, ifaddrmsg, + [ + {family, {enum,uint8_t,family}}, + {prefixlen, uint8_t}, + {flags, {flags,uint8_t,ifa_flags}}, + {scope, uint8_t}, + {index, uint32_t}, + {attributes, {tlvs,rtnetlink_addr}} + ]}. + +{record, newaddr, ifaddrmsg}. +{record, deladdr, ifaddrmsg}. +{record, getaddr, ifaddrmsg}. + +{record, ifinfomsg, + [ + {family, {enum,uchar_t,family}}, + {'_', uchar_t}, + {arphrd, {enum,ushort_t,arphrd}}, + {index, int_t}, + {flags, {flags,uint_t,iff_flags}}, + {change, {flags,uint_t,iff_flags}}, + {attributes, {tlvs,rtnetlink_link}} + ]}. + +{record, newlink, ifinfomsg}. +{record, dellink, ifinfomsg}. +{record, getlink, ifinfomsg}. + +{record, rtmsg, + [ + {family, {enum,uchar_t,family}}, + {dstlen, uchar_t}, + {srclen, uchar_t}, + {tos, uchar_t}, + {table, uchar_t}, %% routing table id + {protocol, {enum,uchar_t,protocol}}, + {scope, uchar_t}, + {rtm_type, uchar_t}, + {flags, uint_t}, + {attributes, {tlvs, rtnetlink_route}} + ]}. + +{record, newroute, rtmsg}. +{record, delroute, rtmsg}. +{record, getroute, rtmsg}. + +{record, ndmsg, + [ + {family, {enum,uint8_t,family}}, + {'_', uint8_t}, + {'_', uint16_t}, + {index, uint32_t}, + {state, uint16_t}, + {flags, uint8_t}, + {nmd_type, uint8_t}, + {attributes, {tlvs, rtnetlink_neigh}} + ]}. + +{record, newneigh, ndmsg}. +{record, delneigh, ndmsg}. +{record, getneigh, ndmsg}. + +%% newrule, delrule, getrule +%% newdisc, deldisc, getdisc +%% newtclass, deltclass, gettclass +%% newtfilter, deltfilter, gettfilter +%% newaction, delaction, getaction +%% newprefix, delprefix +%% newneightbl, getneightbl, setneightbl +%% newnduseropt +%% newaddrlabel +%% getdcb, setdcb + +{record, noop, + [ + ]}. + +{record, error, + [ + {errno, int_t}, + {msg, nlmsghdr}, %% the original header + {data, binary_t} %% truncated data? + ]}. + +{record, done, + [ + {status, uint32_t} %% ? int_t? + ]}. + +{record, overrun, + [ + {status, uint32_t} %% ? int_t? + ]}. diff --git a/deps/netlink/src/netlink_app.erl b/deps/netlink/src/netlink_app.erl new file mode 100644 index 0000000..6bb292b --- /dev/null +++ b/deps/netlink/src/netlink_app.erl @@ -0,0 +1,25 @@ +%%%---- BEGIN COPYRIGHT ------------------------------------------------------- +%%% +%%% Copyright (C) 2012 Feuerlabs, Inc. All rights reserved. +%%% +%%% This Source Code Form is subject to the terms of the Mozilla Public +%%% License, v. 2.0. If a copy of the MPL was not distributed with this +%%% file, You can obtain one at http://mozilla.org/MPL/2.0/. +%%% +%%%---- END COPYRIGHT --------------------------------------------------------- +-module(netlink_app). + +-behaviour(application). + +%% Application callbacks +-export([start/2, stop/1]). + +%% =================================================================== +%% Application callbacks +%% =================================================================== + +start(_StartType, _StartArgs) -> + netlink_sup:start_link(). + +stop(_State) -> + ok. diff --git a/deps/netlink/src/netlink_codec.erl b/deps/netlink/src/netlink_codec.erl new file mode 100644 index 0000000..b611232 --- /dev/null +++ b/deps/netlink/src/netlink_codec.erl @@ -0,0 +1,214 @@ +%%% @author tony <tony@rogvall.se> +%%% @copyright (C) 2013, tony +%%% @doc +%%% Encode / Decode of netlink messages +%%% @end +%%% Created : 21 May 2013 by tony <tony@rogvall.se> + +-module(netlink_codec). + +-export([encode_flags/2]). +-export([decode_flags/2]). +-export([encode_tlv/1, encode_tlv_list/1]). +-export([decode_tlv/1, decode_tlv_list/1]). + +-export([decode/2]). +-export([encode/2]). + +-compile(export_all). + +-include("netlink.hrl"). +-include("netl_codec.hrl"). + +-define(ALIGNTO, 4). +-define(ALIGNMASK, (?ALIGNTO-1)). +-define(NLA_ALIGN(N), (((N)+?ALIGNMASK) band (bnot ?ALIGNMASK))). +-define(NLA_PAD(N), ((?ALIGNTO-((N) band ?ALIGNMASK)) band + ?ALIGNMASK)). +%% may need adjustment (NLA_ALIGN(sizeof(struct nlattr))) +-define(NLA_HDRLEN, 4). +%% -define(NLA_PAD(N), (ALIGN(N) - N)). + +%% prove that: +%% ((N+3) band (bnot 3)) - N == (4 - (N band 3)) band 3 +%% + +encode_flags(Flags, Fun) -> + encode_flags(Flags, 0, Fun). + +encode_flags([], Mask, _Fun) -> Mask; +encode_flags([Flag|Flags], Mask, Fun) -> + BitNum = Fun(Flag), + encode_flags(Flags, Mask+(1 bsl BitNum), Fun). + + +decode_flags(Value, Fun) -> + decode_flags(0, Value, Fun). + +decode_flags(_I, 0, _Fun) -> []; +decode_flags(I, Value, Fun) -> + Bit = (1 bsl I), + if Value band Bit =:= Bit -> + [Fun(I) | decode_flags(I+1, Value band (bnot Bit), Fun)]; + true -> + decode_flags(I+1,Value,Fun) + end. + +decode_attr([{Ri,_Endian,Rv}|Ds], Fun) -> + [ Fun(Ri,Rv) | decode_attr(Ds, Fun)]; +decode_attr([], _Fun) -> + []. + +encode_tlv({Type0,Endian,Data}) -> + Payload = if is_list(Data) -> + encode_tlv_list(Data); + is_binary(Data) -> Data + end, + Type = if is_list(Data) -> + Type0 + 16#8000; + Endian =:= big -> + Type0 + 16#4000; + true -> + Type0 + end, + Len = ?NLA_HDRLEN+byte_size(Payload), + Pad = ?NLA_PAD(Len), + <<Len:16/native-unsigned, Type:16/native-unsigned, + Payload/binary, 0:Pad/unit:8>>. + +encode_tlv_list(TLVs) -> + list_to_binary([encode_tlv(TLV) || TLV <- TLVs]). + +next_tlv(<<Len0:16/native-unsigned, _:16, Data/binary>>) -> + Len = Len0 - ?NLA_HDRLEN, + Pad = ?NLA_PAD(Len), + <<_:Len/binary, _:Pad/unit:8, Data1/binary>> = Data, + Data1. + +decode_tlv(<<Len0:16/native-unsigned, Type0:16/native-unsigned, + Rest/binary>>) -> + Len = Len0 - ?NLA_HDRLEN, + <<Payload:Len/binary, _/binary>> = Rest, + Type = Type0 band 16#3fff, + if Type0 band 16#8000 =:= 16#8000 -> + {Type, native, decode_tlv_list(Payload)}; + Type0 band 16#4000 =:= 16#4000 -> + {Type, big, Payload}; + true -> + {Type, native, Payload} + end. + +decode_tlv_list(<<>>) -> + []; +decode_tlv_list(Data) -> + TLV = decode_tlv(Data), + Data1 = next_tlv(Data), + [TLV | decode_tlv_list(Data1)]. + + +decode(Part= + << Len:32/native-integer, + Type:16/native-integer, + Flags:16/native-integer, + Seq:32/native-integer, + Pid:32/native-integer, + Data/binary >>, Acc) -> + if Len >= byte_size(Part) -> + PayloadLen = Len - 16, + << Payload:PayloadLen/bytes, NextPart/binary >> = Data, + Msg = decode_(Type, Flags, Seq, Pid, Payload), + decode(NextPart, [Msg | Acc]); + true -> + decode(<<>>, [{ error, format} | Acc]) + end; +decode(_PadPart, Acc) -> + lists:reverse(Acc). + +decode_(Type,Flags,Seq,Pid,Payload) -> + MsgType = netl_codec:dec_nlmsg_type(Type), + FlagList = case msg_type(MsgType) of + new -> + decode_flags(Flags, fun netl_codec:dec_nlm_new_flags/1); + get -> + decode_flags(Flags, fun netl_codec:dec_nlm_get_flags/1); + _ -> + decode_flags(Flags, fun netl_codec:dec_nlm_flags/1) + end, + MsgPayload = apply(netl_codec, + list_to_atom("dec_"++atom_to_list(MsgType)), + [{native,Payload}]), + H = #nlmsghdr { type=MsgType, flags=FlagList, seq=Seq, pid=Pid }, + #nlmsg { hdr = H, data=MsgPayload }. + +encode(#nlmsghdr { type=MsgType, flags=FlagList, seq=Seq, pid=Pid }, + MsgPayload ) -> + Type = netl_codec:enc_nlmsg_type(MsgType), + Flags = case msg_type(MsgType) of + new -> + encode_flags(FlagList, fun netl_codec:enc_nlm_new_flags/1); + get -> + encode_flags(FlagList, fun netl_codec:enc_nlm_get_flags/1); + _ -> + encode_flags(FlagList, fun netl_codec:enc_nlm_flags/1) + end, + Payload = apply(netl_codec, + list_to_atom("enc_"++atom_to_list(MsgType)), + [{native,MsgPayload}]), + N = byte_size(Payload), + Pad = ?NLA_PAD(N), + Len = 16 + Pad + N, + << Len:32/native-integer, + Type:16/native-integer, + Flags:16/native-integer, + Seq:32/native-integer, + Pid:32/native-integer, + Payload/binary, + 0:Pad/unit:8 >>. + +msg_type(Type) -> + case Type of + noop -> misc; + error -> misc; + done -> misc; + overrun -> misc; + newlink -> new; + dellink -> del; + getlink -> get; + setlink -> set; + newaddr -> new; + deladdr -> del; + getaddr -> get; + newroute -> new; + delroute -> del; + getroute -> get; + newneigh -> new; + delneigh -> del; + getneigh -> get; + newrule -> new; + delrule -> del; + getrule -> get; + newdisc -> new; + delqdisc -> del; + getqdisc -> get; + newtclass -> new; + deltclass -> del; + gettclass -> get; + newtfilter -> new; + deltfilter -> del; + gettfilter -> get; + newaction -> new; + delaction -> del; + getaction -> get; + newprefix -> new; + getmulticast -> get; + getanycast -> get; + newneightbl -> new; + getneightbl -> get; + setneightbl -> set; + newnduseropt -> new; + newaddrlabel -> new; + deladdrlabel -> del; + getaddrlabel -> get; + getdcb -> get; + setdcb -> set + end. diff --git a/deps/netlink/src/netlink_drv.erl b/deps/netlink/src/netlink_drv.erl new file mode 100644 index 0000000..e390d12 --- /dev/null +++ b/deps/netlink/src/netlink_drv.erl @@ -0,0 +1,135 @@ +%%%---- BEGIN COPYRIGHT ------------------------------------------------------- +%%% +%%% Copyright (C) 2012 Feuerlabs, Inc. All rights reserved. +%%% +%%% This Source Code Form is subject to the terms of the Mozilla Public +%%% License, v. 2.0. If a copy of the MPL was not distributed with this +%%% file, You can obtain one at http://mozilla.org/MPL/2.0/. +%%% +%%%---- END COPYRIGHT --------------------------------------------------------- +%%% @author Tony Rogvall <tony@rogvall.se> +%%% @doc +%%% launch netlink_drv +%%% @end +%%% Created : 30 Nov 2011 by Tony Rogvall <tony@rogvall.se> + +-module(netlink_drv). +-export([open/1, close/1, send/2]). +-export([add_membership/2, + drop_membership/2, + set_rcvbuf/2, set_sndbuf/2, + get_rcvbuf/1, get_sndbuf/1, + get_sizeof/1, + deactivate/1, + activate/1, + activate/2, + debug/2]). + +%% deugging +-compile(export_all). + +-include("netlink.hrl"). + +-define(CMD_ADD_MEMBERSHIP, 1). +-define(CMD_DROP_MEMBERSHIP, 2). +-define(CMD_ACTIVE, 3). +-define(CMD_DEBUG, 4). +-define(CMD_SET_RCVBUF, 5). +-define(CMD_SET_SNDBUF, 6). +-define(CMD_GET_RCVBUF, 7). +-define(CMD_GET_SNDBUF, 8). +-define(CMD_GET_SIZEOF, 9). + +-define(DLOG_DEBUG, 7). +-define(DLOG_INFO, 6). +-define(DLOG_NOTICE, 5). +-define(DLOG_WARNING, 4). +-define(DLOG_ERROR, 3). +-define(DLOG_CRITICAL, 2). +-define(DLOG_ALERT, 1). +-define(DLOG_EMERGENCY, 0). +-define(DLOG_NONE, -1). + +add_membership(Port,Msg) when is_integer(Msg) -> + port_call(Port, ?CMD_ADD_MEMBERSHIP, <<Msg:32>>). + +drop_membership(Port,Msg) when is_integer(Msg) -> + port_call(Port, ?CMD_DROP_MEMBERSHIP, <<Msg:32>>). + +set_rcvbuf(Port,Size) when is_integer(Size), Size >= 0 -> + port_call(Port, ?CMD_SET_RCVBUF, <<Size:32>>). + +set_sndbuf(Port,Size) when is_integer(Size), Size >= 0 -> + port_call(Port, ?CMD_SET_SNDBUF, <<Size:32>>). + +get_rcvbuf(Port) -> + port_call(Port, ?CMD_GET_RCVBUF, <<>>). + +get_sndbuf(Port) -> + port_call(Port, ?CMD_GET_SNDBUF, <<>>). + +get_sizeof(Port) -> + port_call(Port, ?CMD_GET_SIZEOF, <<>>). + +deactivate(Port) -> + activate(Port, 0). + +activate(Port) -> + activate(Port, -1). + +activate(Port, N) when is_integer(N), N >= -1, N < 16#7fffffff -> + port_call(Port, ?CMD_ACTIVE, <<N:32>>). + +debug(Port,Level) when is_atom(Level) -> + L = level(Level), + port_call(Port, ?CMD_DEBUG, <<L:32>>). + +open(Protocol) when is_integer(Protocol), Protocol >= 0 -> + Driver = "netlink_drv", + Path = code:priv_dir(netlink), + io:format("load_driver '~s' from: '~s'\n", [Driver, Path]), + case erl_ddll:load_driver(Path, Driver) of + ok -> + Arg = integer_to_list(Protocol), + erlang:open_port({spawn_driver, Driver++" "++Arg}, [binary]); + {error,Error} -> + io:format("Error: ~s\n", [erl_ddll:format_error_int(Error)]), + erlang:error(Error) + end. + +close(Port) -> + erlang:port_close(Port). + +send(Port, Command) -> + erlang:port_command(Port, Command). + +port_call(Port, Cmd, Data) -> + case erlang:port_control(Port, Cmd, Data) of + <<0>> -> + ok; + <<255,E/binary>> -> + {error, erlang:binary_to_atom(E, latin1)}; + <<254,E/binary>> -> + {error, binary_to_list(E)}; + <<1,Y:8>> -> {ok,Y}; + <<1,Y:16/native-unsigned>> -> {ok, Y}; + <<1,Y:32/native-unsigned>> -> {ok, Y}; + <<1,Y:64/native-unsigned>> -> {ok, Y}; + <<2,X:32/native-unsigned,Y:32/native-unsigned>> -> {ok,{X,Y}}; + <<3,X/binary>> -> {ok,X}; + <<4,X/binary>> -> {ok,binary_to_list(X)} + end. + +%% convert symbolic to numeric level +level(true) -> ?DLOG_DEBUG; +level(false) -> ?DLOG_NONE; +level(debug) -> ?DLOG_DEBUG; +level(info) -> ?DLOG_INFO; +level(notice) -> ?DLOG_NOTICE; +level(warning) -> ?DLOG_WARNING; +level(error) -> ?DLOG_ERROR; +level(critical) -> ?DLOG_CRITICAL; +level(alert) -> ?DLOG_ALERT; +level(emergency) -> ?DLOG_EMERGENCY; +level(none) -> ?DLOG_NONE. + diff --git a/deps/netlink/src/netlink_gen.erl b/deps/netlink/src/netlink_gen.erl new file mode 100644 index 0000000..f0787c5 --- /dev/null +++ b/deps/netlink/src/netlink_gen.erl @@ -0,0 +1,798 @@ +%%% @author tony <tony@rogvall.se> +%%% @copyright (C) 2013, tony +%%% @doc +%%% Generate netlink decoder & header files +%%% @end +%%% Created : 29 May 2013 by tony <tony@rogvall.se> + +-module(netlink_gen). + +-compile(export_all). + +-define(INFILE, "netlink.inc"). +-define(ERL_MOD, "netl_codec"). + +-define(INT_SIZE_32, true). +-define(LONG_SIZE_32, true). + +-ifdef(INT_SIZE_32). +-define(int_t, int32_t). +-define(uint_t, uint32_t). +-else. +-ifdef(INT_SIZE_64). +-define(int_t, int64_t). +-define(uint_t, uint64_t). +-endif. +-endif. + +-ifdef(LONG_SIZE_32). +-define(long_t, int32_t). +-define(ulong_t, uint32_t). +-else. +-ifdef(LONG_SIZE_64). +-define(long_t, int64_t). +-define(ulong_t, uint64_t). +-endif. +-endif. + +-define(short_t, int16_t). +-define(ushort_t, uint16_t). + +-define(char_t, int8_t). +-define(uchar_t, uint8_t). + + +-record(gen, + { + error = 0 :: integer(), %% number of errors detected + defs :: term(), %% Symbol -> Value + enums :: term(), %% Name->[{atom(),integer()}]} + attrs :: term(), %% Name->[{atom(),integer(),type()}] + recs :: term() %% Name->[{atom(),integer(),type()}] + }). + +start() -> + G0 = #gen { defs = dict:new(), + enums = dict:new(), + attrs = dict:new(), + recs = dict:new() }, + {ok,Fd} = file:open(?INFILE, [read]), + try fold_file_terms(fun load_term/3, G0, Fd) of + {ok,G1} -> + ok = emit_hrl(G1), + ok = emit_erl(G1); + Error -> Error + after + file:close(Fd) + end. + +load_term({define,Name,Value},Ln,G) -> + Value1 = lookup_value(Value, G), + D = case dict:find(Name, G#gen.defs) of + {ok,Value1} -> + G#gen.defs; + {ok,_Value2} -> + io:format("~s:~w: warning ~s redefined\n", + [?INFILE,Ln,Name]), + dict:store(Name,Value1,G#gen.defs); + error -> + dict:store(Name,Value1,G#gen.defs) + end, + G#gen { defs = D }; +load_term({enum,Name,Enums}, Ln, G) when is_atom(Name), is_list(Enums) -> + case dict:find(Name, G#gen.enums) of + {ok,_Enums} -> + io:format("~s:~w: error ~s allready defined\n", + [?INFILE,Ln,Name]), + G1 = inc_error(G), + load_enums(Name,Enums,Ln,G1); + error -> + load_enums(Name,Enums,Ln,G) + end; +load_term({attribute,Name,Attrs}, Ln, G) when is_atom(Name), is_list(Attrs) -> + case dict:find(Name, G#gen.attrs) of + {ok,_Attrs} -> + io:format("~s:~w: error ~s allready defined\n", + [?INFILE,Ln,Name]), + G1 = inc_error(G), + load_attrs(Name,Attrs,Ln,G1); + error -> + load_attrs(Name,Attrs,Ln,G) + end; +load_term({record,Name,Fields}, Ln, G) when is_atom(Name), is_list(Fields) -> + case dict:find(Name, G#gen.recs) of + {ok,_Attrs} -> + io:format("~s:~w: error ~s allready defined\n", + [?INFILE,Ln,Name]), + G1 = inc_error(G), + load_fields(Name,Fields,Ln,G1); + error -> + load_fields(Name,Fields,Ln,G) + end; +load_term({record,Name,Type}, Ln, G) when is_atom(Name), is_atom(Type) -> + case dict:find(Type, G#gen.recs) of + error -> + io:format("~s:~w: error ~s not defined\n", + [?INFILE,Ln,Type]), + G1 = inc_error(G), + G2 = load_fields(Type,[],Ln,G1), + load_fields(Name,Type,Ln,G2); + {ok,_} -> + case dict:find(Name, G#gen.recs) of + {ok,_Attrs} -> + io:format("~s:~w: error ~s allready defined\n", + [?INFILE,Ln,Name]), + G1 = inc_error(G), + load_fields(Name,Type,Ln,G1); + error -> + load_fields(Name,Type,Ln,G) + end + end; +load_term(Other, Ln, G) -> + io:format("~s:~w: error badly formed term ~p\n", [?INFILE,Ln,Other]), + inc_error(G). + + +%% +%% Load enums, enumerate warn about multiple usage of names and values! +%% +load_enums(Name,Enums0,Ln,G) -> + Enums = enumerate(Enums0,G), + G1 = check_enumeration(Name,Enums,Ln,G), + D = dict:store(Name, Enums, G1#gen.enums), + G1#gen { enums = D}. + +check_enumeration(Name,[{E,V}|Es],Ln,G) -> + case lists:keyfind(E,1,Es) of + false -> + case lists:keyfind(V,2,Es) of + false -> + check_enumeration(Name,Es,Ln,G); + {E1,V} -> + io:format("~s:~w: value for ~w also used by ~w\n", + [?INFILE,Ln,E,E1]), + G1 = inc_error(G), + check_enumeration(Name,Es,Ln,G1) + end; + {E,_V1} -> + io:format("~s:~w: enum ~s multiply defined\n", + [?INFILE,Ln,E]), + G1 = inc_error(G), + check_enumeration(Name,Es,Ln,G1) + end; +check_enumeration(_Name, [], _Ln,G) -> + G. + +%% generate uniq values for names not assigne values +enumerate(Enums,G) -> + Enums1 = lists:map(fun({E,V}) -> {E,lookup_value(V,G)}; + (E) -> E + end, Enums), + Vs0 = lists:foldl(fun({_E,V},Acc) -> [V|Acc]; + (_E,Acc) -> Acc + end, [], Enums1), + Vs1 = lists:usort(Vs0), + enumerate(Enums1, 0, Vs1). + +enumerate([{E,V}|Es], I, Vs) when is_atom(E) -> + [{E,V}|enumerate(Es, I, Vs)]; +enumerate(Es0=[E|Es], I, Vs) when is_atom(E) -> + case lists:member(I,Vs) of + true -> enumerate(Es0,I+1,Vs); + false -> [{E,I}|enumerate(Es,I+1,Vs)] + end; +enumerate([],_I,_Vs) -> + []. + +%% +%% Load record fields +%% +load_fields(Name,Type,_Ln,G) when is_atom(Type) -> + D = dict:store(Name, Type, G#gen.recs), + G#gen { recs = D }; +load_fields(Name,Fields,Ln,G) -> + Fields1 = [{F,I,T} || + {I,{F,T}} <- + lists:zip(lists:seq(1,length(Fields)),Fields)], + G1 = check_fields(Name,Fields1,Ln,G), + D = dict:store(Name, Fields1, G1#gen.recs), + G1#gen { recs = D }. + +check_fields(Name,[{'_',_I,T}|Fs],Ln,G) -> + G1 = check_type({record,Name,'_'}, T, Ln, G), + check_fields(Name, Fs, Ln, G1); +check_fields(Name,[{F,_I,T}|Fs],Ln,G) -> + case lists:keymember(F,1,Fs) of + true -> + io:format("~s:~w: field ~s multiply defined\n", + [?INFILE,Ln,F]), + G1 = inc_error(G), + G2 = check_type({record,Name,F}, T, Ln, G1), + check_fields(Name, Fs, Ln, G2); + false -> + G1 = check_type({record,Name,F}, T, Ln, G), + check_fields(Name, Fs, Ln, G1) + end; +check_fields(_Name,[],_Ln,G) -> + G. +%% +%% Load attribute fields +%% +load_attrs(Name,Attrs,Ln,G) -> + Attrs1 = [{A,I,T} || + {I,{A,T}} <- lists:zip(lists:seq(0,length(Attrs)-1),Attrs)], + G1 = check_attrs(Name,Attrs1,Ln,G), + D = dict:store(Name, Attrs1, G1#gen.attrs), + G1#gen { attrs = D }. + +check_attrs(Name,[{A,_I,T}|As],Ln,G) -> + case lists:keymember(A,1,As) of + true -> + io:format("~s:~w: attribute ~s multiply defined\n", + [?INFILE,Ln,A]), + G1 = inc_error(G), + G2 = check_type({attribute,Name,A}, T, Ln, G1), + check_attrs(Name, As, Ln, G2); + false -> + G1 = check_type({attribute,Name,A}, T, Ln, G), + check_attrs(Name, As, Ln, G1) + end; +check_attrs(_Name,[],_Ln,G) -> + G. + + +emit_hrl(G) -> + {ok,Fd} = file:open(?ERL_MOD++".hrl", [write]), + try + dict:fold( + fun(K,V,_A) -> + io:format(Fd, "-define(~s, ~w).\n", [K, V]) + end, ok, G#gen.defs), + dict:fold( + fun(K,V,_A) -> + Fields = lookup_fields(V, G), + Fs = list_to_tuple([N || {N,_I,_Type} <- Fields, N =/= '_']), + io:format(Fd, "-record(~s, ~w).\n", [K, Fs]) + end, ok, G#gen.recs) + of + R -> R + after + file:close(Fd) + end. + + +emit_erl(G) -> + {ok,Fd} = file:open(?ERL_MOD++".erl", [write]), + io:format(Fd, "-module(~s).\n", [?ERL_MOD]), + io:format(Fd, "-include(~p).\n", [?ERL_MOD++".hrl"]), + try emit_codec_(Fd, G) of + ok -> ok + after + file:close(Fd) + end. + +emit_codec_(Fd, G) -> + dict:fold( + fun(Name,_Tab,_) -> + io:format(Fd, "-export([dec_~s/1, enc_~s/1]).\n", + [Name,Name]) + end, ok, G#gen.enums), + dict:fold( + fun(Name,_Tab,_) -> + io:format(Fd, "-export([dec_~s/1, enc_~s/1]).\n", + [Name,Name]) + end, ok, G#gen.attrs), + dict:fold( + fun(Name,_Tab,_) -> + io:format(Fd, "-export([dec_~s/1, enc_~s/1]).\n", + [Name,Name]) + end, ok, G#gen.recs), + + + dict:fold( + fun(Name,Tab,_) -> + %% decode + lists:foreach( + fun({Enum,Value}) -> + io:format(Fd,"dec_~s(~w) -> ~s;\n", [Name,Value,Enum]) + end, Tab), + io:format(Fd,"dec_~s(V) -> V.\n", [Name]), + %% encode + lists:foreach( + fun({Enum,Value}) -> + io:format(Fd,"enc_~s(~s) -> ~w;\n", [Name,Enum,Value]) + end, Tab), + io:format(Fd,"enc_~s(V) when is_integer(V) -> V;\n", [Name]), + io:format(Fd,"enc_~s(E) -> erlang:error({undefined,E}).\n", + [Name]) + end, ok, G#gen.enums), + + dict:fold( + fun(Name,Tab0,_) -> + %% extend addr_t => ipv4_addr_t | ipv6_addr_t + Tab = lists:foldr( + fun({A,I,addr_t},Acc) -> + [{A,I,ipv4_addr_t},{A,I,ipv6_addr_t} | Acc]; + (E,Acc) -> [E|Acc] + end, [], Tab0), + lists:foreach( + fun({Attr,Index,Type}) -> + {M1,R1} = match_code(Type,native,"X",G), + io:format(Fd, + "dec_~s({~w,native,<<~s>>}) ->\n" + " {~s,~s};\n", + [Name,Index,M1,Attr,R1]), + {M2,R2} = match_code(Type,big,"X",G), + io:format(Fd, + "dec_~s({~w,big,<<~s>>}) ->\n" + " {~s,~s};\n", + [Name,Index,M2,Attr,R2]) + end, Tab), + io:format(Fd,"dec_~s({I,_Endian,Bin}) -> {I,Bin}.\n", [Name]), + + lists:foreach( + fun({Attr,Index,Type}) -> + {M1,C1} = gen_code(Type,native,"X",G), + io:format(Fd,"enc_~s({~s,native,~s}) ->\n" + " {~w,native,<<~s>>};\n", + [Name,Attr,M1,Index,C1]), + {M2,C2} = gen_code(Type,big,"X",G), + io:format(Fd,"enc_~s({~s,big,~s}) ->\n" + " {~w,big,<<~s>>};\n", + [Name,Attr,M2,Index,C2]) + end, Tab), + io:format(Fd,"enc_~s({I,Endian,X}) -> {I,Endian,X}.\n", [Name]) + end, ok, G#gen.attrs), + + dict:fold( + fun(Name,RecType,_) -> + Fields = lookup_fields(RecType, G), + Named = [{Fi,Ix,Ti} || {Fi,Ix,Ti} <- Fields, Fi =/= '_'], + {Ms,Rs} = match_record_code(Fields, native, "X", G), + M = io_list_join(Ms, ","), + Rs1 = lists:map(fun({{Fi,_,_Ti},Ri}) -> + [atom_to_list(Fi),"=",Ri] + end, lists:zip(Named,Rs)), + R1 = ["#",atom_to_list(Name),"{", io_list_join(Rs1,","), "}"], + + io:format(Fd,"dec_~s({native,<<~s>>}) ->\n" + " ~s.\n", + [Name,M,R1]), + + {Ts,Bs} = gen_record_code(Fields, native, "X", G), + Ts1 = lists:map(fun({{Fi,_,_Ti},Ri}) -> + [atom_to_list(Fi),"=",Ri] + end, lists:zip(Named,Ts)), + R2 = ["#",atom_to_list(Name),"{", io_list_join(Ts1,","), "}"], + B = io_list_join(Bs, ","), + io:format(Fd,"enc_~s({_Endian,~s}) -> <<~s>>.\n", + [Name,R2,B]), + ok + end, ok, G#gen.recs). + + +check_type(Ctx, {array,T}, Ln, G) -> + case is_base_type(T) of + true -> + G; + false -> + io:format("~s:~w: type ~w not allowed as base type in ~w\n", + [?INFILE,Ln,T,Ctx]), + inc_error(G) + end; +check_type(_Ctx, {enum,Type,Enum}, Ln, G) + when is_atom(Type), is_atom(Enum) -> + case is_integer_type(Type) of + true -> + case dict:find(Enum, G#gen.enums) of + {ok,_} -> G; + error -> + io:format("~s:~w: enum type ~s not defined\n", + [?INFILE,Ln,Enum]), + inc_error(G) + end; + false -> + io:format("~s:~w: enum must have an integer base type\n", + [?INFILE,Ln]), + inc_error(G) + end; +check_type(_Ctx, {flags,Type,Enum}, Ln, G) + when is_atom(Type), is_atom(Enum) -> + case is_unsigned_type(Type) of + true -> + case dict:find(Enum, G#gen.enums) of + {ok,_} -> G; + error -> + io:format("~s:~w: enum type ~s not defined\n", + [?INFILE,Ln,Enum]), + inc_error(G) + end; + false -> + io:format("~s:~w: flags must have an unsigned base type\n", + [?INFILE,Ln]), + inc_error(G) + end; +check_type(Ctx, {tlvs,Name}, Ln, G) -> + %% fixme, check that Ctx is {attribute,...} + case dict:find(Name, G#gen.attrs) of + error -> + io:format("~s:~w: attribute type ~s name not found in ~w\n", + [?INFILE,Ln,Name,Ctx]), + inc_error(G); + {ok,_} -> + G + end; +check_type(Ctx, T, Ln, G) -> + case is_base_type(T) of + true -> G; + false -> + case T of + string_t -> G; + binary_t -> G; + Type when is_atom(Type) -> + case lookup_type(Type, G) of + false -> + io:format("~s:~w: type ~s name not found in ~w\n", + [?INFILE,Ln,Type,Ctx]), + inc_error(G); + _Typedef -> + G + end; + _ -> + io:format("~s:~w: type ~w not allowed in ~w\n", + [?INFILE,Ln,T,Ctx]), + inc_error(G) + end + end. + +is_base_type(T) -> + case is_integer_type(T) of + true -> true; + false -> + case T of + addr_t -> true; + ether_addr_t -> true; + ipv4_addr_t -> true; + ipv6_addr_t -> true; + _ -> false + end + end. + +is_integer_type(T) -> + is_unsigned_type(T) orelse is_signed_type(T). + +is_unsigned_type(T) -> + case T of + ulong_t -> true; + ushort_t -> true; + uchar_t -> true; + uint_t -> true; + uint8_t -> true; + uint16_t -> true; + uint32_t -> true; + uint64_t -> true; + _ -> false + end. + +is_signed_type(T) -> + case T of + long_t -> true; + int_t -> true; + short_t -> true; + char_t -> true; + int8_t -> true; + int16_t -> true; + int32_t -> true; + int64_t -> true; + _ -> false + end. +%% +%% generate match code +%% {BitMatch, TermCode} +%% +match_code(int_t, E, X, G) -> match_code(?int_t, E, X, G); +match_code(uint_t, E, X, G) -> match_code(?uint_t, E, X, G); +match_code(long_t, E, X, G) -> match_code(?long_t, E, X, G); +match_code(ulong_t, E, X, G) -> match_code(?ulong_t, E, X, G); +match_code(short_t, E, X, G) -> match_code(?short_t, E, X, G); +match_code(ushort_t, E, X, G) -> match_code(?ushort_t, E, X, G); +match_code(char_t, E, X, G) -> match_code(?char_t, E, X, G); +match_code(uchar_t, E, X, G) -> match_code(?uchar_t, E, X, G); + +match_code(uint64_t,native,X,_G) -> match_int_code(X,64,unsigned,native); +match_code(uint32_t,native,X,_G) -> match_int_code(X,32,unsigned,native); +match_code(uint16_t,native,X,_G) -> match_int_code(X,16,unsigned,native); +match_code(uint8_t,native,X,_G) -> match_int_code(X,8,unsigned,native); +match_code(uint64_t,big,X,_G) -> match_int_code(X,64,unsigned,big); +match_code(uint32_t,big,X,_G) -> match_int_code(X,32,unsigned,big); +match_code(uint16_t,big,X,_G) -> match_int_code(X,16,unsigned,big); +match_code(uint8_t,big,X,_G) -> match_int_code(X,8,unsigned,big); +match_code(uint64_t,little,X,_G) -> match_int_code(X,64,unsigned,little); +match_code(uint32_t,little,X,_G) -> match_int_code(X,32,unsigned,little); +match_code(uint16_t,little,X,_G) -> match_int_code(X,16,unsigned,little); +match_code(uint8_t,little,X,_G) -> match_int_code(X,8,unsigned,little); + +match_code(int64_t,native,X,_G) -> match_int_code(X,64,signed,native); +match_code(int32_t,native,X,_G) -> match_int_code(X,32,signed,native); +match_code(int16_t,native,X,_G) -> match_int_code(X,16,signed,native); +match_code(int8_t,native,X,_G) -> match_int_code(X,8,signed,native); +match_code(int64_t,big,X,_G) -> match_int_code(X,64,signed,big); +match_code(int32_t,big,X,_G) -> match_int_code(X,32,signed,big); +match_code(int16_t,big,X,_G) -> match_int_code(X,16,signed,big); +match_code(int8_t, big,X,_G) -> match_int_code(X,8,signed,big); +match_code(int64_t,little,X,_G) -> match_int_code(X,64,signed,little); +match_code(int32_t,little,X,_G) -> match_int_code(X,32,signed,little); +match_code(int16_t,little,X,_G) -> match_int_code(X,16,signed,little); +match_code(int8_t,little,X,_G) -> match_int_code(X,8,signed,little); +match_code(binary_t,_Endian,X,_G) -> + {[X,"/binary"],X}; +match_code(string_t,_Endian,X,_G) -> + {[X,"/binary"], ["binary_to_list(hd(binary:split(",X,",","<<0>>)))"]}; + +match_code({enum,BaseType,Name},Endian,X,G) -> + Xe = X++"e", + Decode = "dec_"++atom_to_list(Name), + {Match,Value} = match_code(BaseType,Endian,Xe,G), + {Match,[Decode,"(",Value,")"]}; +match_code({flags,BaseType,Name},Endian,X,G) -> + Xf = X++"f", + Decode = "dec_"++atom_to_list(Name), + {Match,Value} = match_code(BaseType,Endian,Xf,G), + {Match,["netlink_codec:decode_flags(",Value,",fun ",Decode,"/1)"]}; +match_code({array,BaseType},Endian,X,G) -> + %% [Xi || <<Xi:32/unsigned-big>> <= X ] + Xi = X++"i", + %% Well, Xi must be equal to Value here! + {Match,Value} = match_code(BaseType,Endian,Xi,G), + {[X,"/binary"], ["[",Value," || <<",Match,">> <= ",X,"]"] }; +match_code({tlvs,Name},_Endian,X,_G) -> + Xi = X++"i", + Decode = "dec_"++atom_to_list(Name), + {[X,"/binary"], + ["[",Decode,"(",Xi,") || ", + Xi," <- netlink_codec:decode_tlv_list(",X,")]"]}; +match_code(ether_addr_t, _, X,_G) -> + Xs = [X++integer_to_list(I) || I <- lists:seq(1,6)], + {string:join(Xs,","), ["{", string:join(Xs,","), "}"]}; +match_code(ipv4_addr_t, _, X,_G) -> + Xi = [X++integer_to_list(I) || I <- lists:seq(1,4)], + Xm = [J++":8" || J <- Xi], + {string:join(Xm,","), + ["{", string:join(Xi,","), "}"]}; +match_code(ipv6_addr_t,_,X,_G) -> + Xi = [X++integer_to_list(I) || I <- lists:seq(1,8)], + Xm = [J++":16" || J <- Xi], + {string:join(Xm,","), + ["{", string:join(Xi,","), "}"]}; +%% match_code(addr_t,_,X,_G) -> +%% Xi = [X++integer_to_list(I) || I <- lists:seq(1,4)], +%% Xm = [J++":8" || J <- Xi], +%% {string:join(Xm,","), +%% ["{", string:join(Xi,","), "}"]}; +match_code(Name,Endian,X,G) -> + case dict:find(Name, G#gen.recs) of + error -> + %% assume attribute! + {ok,_} = dict:find(Name, G#gen.attrs), + Decode = "dec_"++atom_to_list(Name), + {[X,"/binary"], [Decode,"(netlink_codec:decode_tlv(",X,"))"]}; + {ok,RecType} -> + Fields = lookup_fields(RecType,G), + Named = [{Fi,Ix,Ti} || {Fi,Ix,Ti} <- Fields, Fi =/= '_'], + {Ms,Rs} = match_record_code(Fields, Endian, X, G), + M = io_list_join(Ms, ","), + Rs1 = lists:map(fun({{Fi,_,_Ti},Ri}) -> + [atom_to_list(Fi),"=",Ri] + end, lists:zip(Named,Rs)), + R = ["#",atom_to_list(Name),"{", io_list_join(Rs1,","), "}"], + {M, R} + end. + +match_record_code(Fs, Endian, X, G) -> + match_record_code_(Fs, Endian, X, G, [], []). + +match_record_code_([{'_',_Ix,Type}|Fs], Endian, X, G, Ms, Rs) -> + {M,_R} = match_code(Type, Endian, "_", G), + match_record_code_(Fs, Endian, X, G, [M|Ms], Rs); +match_record_code_([{_Field,Ix,Type}|Fs], Endian, X, G, Ms, Rs) -> + Xi = X++integer_to_list(Ix), + {M,R} = match_code(Type, Endian, Xi, G), + match_record_code_(Fs, Endian, X, G, [M|Ms], [R|Rs]); +match_record_code_([], _Endian, _X, _G, Ms, Rs) -> + {lists:reverse(Ms), lists:reverse(Rs)}. + +%% +%% X:Size/<sign>-<endian> => Decode +%% {BitMatch,Decode} +%% +match_int_code(X,Size,Sign,Endian) -> + {[X,":",integer_to_list(Size),"/", + atom_to_list(Sign),"-",atom_to_list(Endian)], X}. + +%% +%% generate generate-code +%% return {Encode, BitConstruct} +%% +gen_code(int_t, E, X, G) -> gen_code(?int_t, E, X, G); +gen_code(uint_t, E, X, G) -> gen_code(?uint_t, E, X, G); +gen_code(long_t, E, X, G) -> gen_code(?long_t, E, X, G); +gen_code(ulong_t, E, X, G) -> gen_code(?ulong_t, E, X, G); +gen_code(short_t, E, X, G) -> gen_code(?short_t, E, X, G); +gen_code(ushort_t, E, X, G) -> gen_code(?ushort_t, E, X, G); +gen_code(char_t, E, X, G) -> gen_code(?char_t, E, X, G); +gen_code(uchar_t, E, X, G) -> gen_code(?uchar_t, E, X, G); + +gen_code(uint64_t,native,X,_G) -> gen_int_code(X,64,unsigned,native); +gen_code(uint32_t,native,X,_G) -> gen_int_code(X,32,unsigned,native); +gen_code(uint16_t,native,X,_G) -> gen_int_code(X,16,unsigned,native); +gen_code(uint8_t,native,X,_G) -> gen_int_code(X,8,unsigned,native); +gen_code(uint64_t,big,X,_G) -> gen_int_code(X,64,unsigned,big); +gen_code(uint32_t,big,X,_G) -> gen_int_code(X,32,unsigned,big); +gen_code(uint16_t,big,X,_G) -> gen_int_code(X,16,unsigned,big); +gen_code(uint8_t,big,X,_G) -> gen_int_code(X,8,unsigned,big); +gen_code(uint64_t,little,X,_G) -> gen_int_code(X,64,unsigned,little); +gen_code(uint32_t,little,X,_G) -> gen_int_code(X,32,unsigned,little); +gen_code(uint16_t,little,X,_G) -> gen_int_code(X,16,unsigned,little); +gen_code(uint8_t,little,X,_G) -> gen_int_code(X,8,unsigned,little); + +gen_code(int64_t,native,X,_G) -> gen_int_code(X,64,signed,native); +gen_code(int32_t,native,X,_G) -> gen_int_code(X,32,signed,native); +gen_code(int16_t,native,X,_G) -> gen_int_code(X,16,signed,native); +gen_code(int8_t,native,X,_G) -> gen_int_code(X,8,signed,native); +gen_code(int64_t,big,X,_G) -> gen_int_code(X,64,signed,big); +gen_code(int32_t,big,X,_G) -> gen_int_code(X,32,signed,big); +gen_code(int16_t,big,X,_G) -> gen_int_code(X,16,signed,big); +gen_code(int8_t,big,X,_G) -> gen_int_code(X,8,signed,big); +gen_code(int64_t,little,X,_G) -> gen_int_code(X,64,signed,little); +gen_code(int32_t,little,X,_G) -> gen_int_code(X,32,signed,little); +gen_code(int16_t,little,X,_G) -> gen_int_code(X,16,signed,little); +gen_code(int8_t,little,X,_G) -> gen_int_code(X,8,signed,little); + +gen_code(binary_t, _Endian, X,_G) -> + {X, X}; +gen_code(string_t, _Endian, X,_G) -> + {X, ["(erlang:iolist_to_binary([",X,",0","]))/binary"]}; + +gen_code({enum,BaseType,Name},Endian,X,G) -> + Encode = "enc_"++atom_to_list(Name), + E = ["(",Encode,"(",X,"))"], + {_M,C} = gen_code(BaseType,Endian,E,G), + {X,C}; + +gen_code({flags,BaseType,Name},Endian,X,G) -> + Encode = "enc_"++atom_to_list(Name), + E = ["(","netlink_codec:encode_flags(",X,",fun ",Encode,"/1))"], + {_M,C} = gen_code(BaseType,Endian,E,G), + {X,C}; + +gen_code({array,BaseType},Endian,X,G) -> + Xi = X++"i", + {_M,C} = gen_code(BaseType,Endian,Xi,G), %% M=Xi! only simple base types! + {X, ["(<< <<",C,">>", " || ",Xi," <- ",X,">>)/binary"]}; + +gen_code({tlvs,Name},_Endian,X,_G) -> + Xi = X++"i", + Encode = "enc_"++atom_to_list(Name), + {X, [ "(netlink_codec:encode_tlv_list(", + "[",Encode,"(",Xi,") || ", Xi," <- ",X,"]", "))/binary"]}; + +gen_code(ether_addr_t,_,X,_G) -> + Xi = [X++integer_to_list(I) || I <- lists:seq(1,6)], + Xm = [J++":8" || J <- Xi], + {["{", string:join(Xi,","),"}"], string:join(Xm,",") }; +gen_code(ipv4_addr_t,_,X,_G) -> + Xi = [X++integer_to_list(I) || I <- lists:seq(1,4)], + Xm = [J++":8" || J <- Xi], + {["{", string:join(Xi,","),"}"], string:join(Xm,",")}; +gen_code(ipv6_addr_t,_,X,_G) -> + Xi = [X++integer_to_list(I) || I <- lists:seq(1,8)], + Xm = [J++":16" || J <- Xi], + {["{", string:join(Xi,","), "}"], string:join(Xm,",")}; +%% gen_code(addr_t,_,X,_G) -> +%% %% FIXME: use address family from message ? +%% Xi = [X++integer_to_list(I) || I <- lists:seq(1,4)], +%% Xm = [J++":8" || J <- Xi], +%% {["{", string:join(Xi,","),"}"], string:join(Xm,",")}; +gen_code(Name,Endian,X,G) -> + case dict:find(Name, G#gen.recs) of + error -> + %% assume attribute! + Encode = "enc_"++atom_to_list(Name), + {X, [ "(netlink_codec:encode_tlv(",Encode,"(",X,")))"]}; + {ok,RecType} -> + Fields = lookup_fields(RecType,G), + Named = [{Fi,Ix,Ti} || {Fi,Ix,Ti} <- Fields, Fi =/= '_'], + %% must be record + {Ts,Bs} = gen_record_code(Fields, Endian, X, G), + Ts1 = lists:map(fun({{Fi,_,_Ti},Ri}) -> + [atom_to_list(Fi),"=",Ri] + end, lists:zip(Named,Ts)), + R = ["#",atom_to_list(Name),"{", io_list_join(Ts1,","), "}"], + B = io_list_join(Bs, ","), + {R, B} + end. + + + +gen_record_code(Fs, Endian, X, G) -> + gen_record_code_(Fs, Endian, X, G, [], []). + +gen_record_code_([{'_',_Ix,Type}|Fs], Endian, X, G, Ms, Bs) -> + {_M,B} = gen_code(Type, Endian, "0", G), + gen_record_code_(Fs, Endian, X, G, Ms, [B|Bs]); +gen_record_code_([{_Field,Ix,Type}|Fs], Endian, X, G, Ms, Bs) -> + Xi = X++integer_to_list(Ix), + {M,B} = gen_code(Type, Endian, Xi, G), + gen_record_code_(Fs, Endian, X, G, [M|Ms], [B|Bs]); +gen_record_code_([], _Endian, _X, _G, Ms, Bs) -> + {lists:reverse(Ms), lists:reverse(Bs)}. + +%% return {TermMatch,BitConstruct} +gen_int_code(X,Size,Sign,Endian) -> + {X, [X,":",integer_to_list(Size),"/", + atom_to_list(Sign),"-",atom_to_list(Endian)]}. + +%% +%% io_list_join like string:join but for io_lists +%% +io_list_join([], _Sep) -> []; +io_list_join([A], _Sep) -> [A]; +io_list_join([A|As], Sep) -> [A,Sep|io_list_join(As,Sep)]. + +%% +%% Get record indirections +%% +lookup_fields(Name, G) when is_atom(Name) -> + case dict:find(Name, G#gen.recs) of + {ok,Name1} -> + lookup_fields(Name1, G) + end; +lookup_fields(Fields,_G) when is_list(Fields) -> + Fields. + +%% +%% Lookup defined value +%% + +lookup_value(Value, _G) when is_integer(Value) -> + Value; +lookup_value(Name, G) when is_atom(Name) -> + case dict:find(Name, G#gen.defs) of + {ok,Name} -> Name; %% recursive! + {ok,Value} when is_atom(Value) -> lookup_value(Value,G); + {ok,Value} when is_integer(Value) -> Value; + error -> Name + end. + +%% lookup named type (record / attribute) +lookup_type(Name, G) when is_atom(Name) -> + case dict:find(Name, G#gen.attrs) of + error -> + case dict:find(Name, G#gen.recs) of + error -> + false; + {ok,Value} -> {attribute,Name,Value} + end; + {ok,Value} -> {record,Name,Value} + end. + + +inc_error(G) -> + G#gen { error = G#gen.error + 1}. + + +%% util to fold all terms in a file +fold_file_terms(Fun, Acc, Fd) -> + fold_file_terms(Fun, Acc, 1, Fd). + +fold_file_terms(Fun, Acc, Line, Fd) -> + case io:read(Fd, '', Line) of + {ok,Term,EndLine} -> + fold_file_terms(Fun, Fun(Term,Line,Acc), EndLine,Fd); + {error,Error,Line} -> + io:format("parse error:~w: ~p\n", [Line,Error]), + {error,Error}; + {eof,_Line} -> + {ok,Acc} + end. + diff --git a/deps/netlink/src/netlink_stat.erl b/deps/netlink/src/netlink_stat.erl new file mode 100644 index 0000000..eb7775e --- /dev/null +++ b/deps/netlink/src/netlink_stat.erl @@ -0,0 +1,115 @@ +%%% @author tony <tony@rogvall.se> +%%% @copyright (C) 2013, tony +%%% @doc +%%% Get network statistics +%%% @end +%%% Created : 18 Aug 2013 by tony <tony@rogvall.se> + +-module(netlink_stat). + +-compile(export_all). + +-include("../include/netlink.hrl"). + +get_value() -> + get_value("*"). + +get_value("") -> + get_value("*"); +get_value(Counter) -> + case string:tokens(Counter, ".") of + [] -> get_all_counters(); + ["*"] -> get_all_counters(); + ["*","*"] -> get_all_counters(); + [Name,"*"] -> get_all_counters(Name); + [Name] -> get_all_counters(Name); + ["*",Var] -> + Field = list_to_atom(Var), + Fi = index(Field, record_info(fields, rtnl_link_stats)), + if Fi =:= 0 -> + []; + true -> + {ok,Ifs} = inet:getiflist(), + select_counters_(Ifs, Fi+1, Var, []) + end; + [Name,Var] -> + Field = list_to_atom(Var), + {ok,S} = get_statistics(Name), + case index(Field, record_info(fields, rtnl_link_stats)) of + 0 -> []; + Fi -> [{Counter,element(Fi+1, S)}] + end + end. + +get_all_counters() -> + {ok,Ifs} = inet:getiflist(), + get_all_counters_(Ifs,[]). + +get_all_counters(Name) -> + {ok,S} = get_statistics(Name), + Acc = get_counters_(Name, 2, record_info(fields, rtnl_link_stats),S,[]), + lists:reverse(Acc). + +select_counters_([Name|As],Fi,Var,Acc) -> + {ok,S} = get_statistics(Name), + Value = element(Fi,S), + select_counters_(As,Fi,Var,[{Name++"."++Var,Value}|Acc]); +select_counters_([], _Fi, _Var, Acc) -> + lists:reverse(Acc). + +get_all_counters_([Name|As],Acc) -> + {ok,S} = get_statistics(Name), + Acc1 = get_counters_(Name,2,record_info(fields, rtnl_link_stats),S,Acc), + get_all_counters_(As,Acc1); +get_all_counters_([], Acc) -> + lists:reverse(Acc). + +get_counters_(Name, I, [F|Fs], S, Acc) -> + Var = atom_to_list(F), + get_counters_(Name, I+1, Fs, S, [{Name++"."++Var, element(I,S)} |Acc]); +get_counters_(_Name, _I, [], _S, Acc) -> + Acc. + +%% +%% Find first Key in Position Pos in the List +%% return the position in the list or 0 if not found +index(Value, List) -> + index_(1, Value, List). + +index_(I,Value,[Value|_List]) -> I; +index_(I,Value,[_|List]) -> index_(I+1,Value,List); +index_(_I,_Value,[]) -> 0. + + +get_statistics(Interface) -> + netlink:start(), + {ok,Ref} = netlink:subscribe(Interface), + netlink:invalidate(Interface, [stats,stats64]), + ok = netlink:get_match(link, inet, [{stats,native,[]}]), + Res = get_stats64(Ref,1000), + flush_stats(Ref), + netlink:unsubscribe(Ref), + case Res of + {ok,Stats} -> + #rtnl_link_stats{} = R =list_to_tuple([rtnl_link_stats | Stats]), + {ok,R}; + Error -> + Error + end. + +get_stats64(Ref,Timeout) -> + receive + {netlink,Ref,_Interface,stats64,_Old,New} -> + {ok,New} + after Timeout -> + {error,timeout} + end. + +flush_stats(Ref) -> + receive + _Msg={netlink,Ref,_Interface,_,_Old,_New} -> + %% io:format("flushed: ~p\n", [_Msg]), + flush_stats(Ref) + after 0 -> + ok + end. diff --git a/deps/netlink/src/netlink_sup.erl b/deps/netlink/src/netlink_sup.erl new file mode 100644 index 0000000..0d5a5d7 --- /dev/null +++ b/deps/netlink/src/netlink_sup.erl @@ -0,0 +1,36 @@ +%%%---- BEGIN COPYRIGHT ------------------------------------------------------- +%%% +%%% Copyright (C) 2012 Feuerlabs, Inc. All rights reserved. +%%% +%%% This Source Code Form is subject to the terms of the Mozilla Public +%%% License, v. 2.0. If a copy of the MPL was not distributed with this +%%% file, You can obtain one at http://mozilla.org/MPL/2.0/. +%%% +%%%---- END COPYRIGHT --------------------------------------------------------- + +-module(netlink_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). + +%% =================================================================== +%% API functions +%% =================================================================== + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +%% =================================================================== +%% Supervisor callbacks +%% =================================================================== + +init([]) -> + C = {netlink, {netlink, start_link, []}, + permanent, 5000, worker, [netlink]}, + {ok, { {one_for_one, 5, 10}, [C]}}. + diff --git a/deps/netlink/tetrapak/build_drv.erl b/deps/netlink/tetrapak/build_drv.erl new file mode 100644 index 0000000..b4359aa --- /dev/null +++ b/deps/netlink/tetrapak/build_drv.erl @@ -0,0 +1,11 @@ +-task({"build:drv", "Build the netlink driver"}). +-task({"clean:drv", "Clean the netlink driver"}). + +run("build:drv", _) -> + tetrapak:outputcmd(tetrapak:subdir("c_src"), "make", [cflags(), "all"]); + +run("clean:drv", _) -> + tetrapak:outputcmd(tetrapak:subdir("c_src"), "make", [cflags(), "clean"]). + +cflags() -> + ["CFLAGS=", "-O2 ", ["-I", code:root_dir(), "/erts-", erlang:system_info(version), "/include"]]. diff --git a/deps/netlink/tetrapak/config.ini b/deps/netlink/tetrapak/config.ini new file mode 100644 index 0000000..0cd3ed4 --- /dev/null +++ b/deps/netlink/tetrapak/config.ini @@ -0,0 +1,8 @@ +[build] +version = "~t.~o~~~c" + +[package] +maintainer = "Tony Rogvall <tony@feuerlabs.com>" +exclude = "\\.gitignore|README.md|libnl" +architecture = host + |