mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-07-27 08:31:44 +08:00
update 2026-07-10 22:10:07
This commit is contained in:
parent
ddc4538935
commit
8a04c3469b
@ -1,26 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=fibocom-dial
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/fibocom-dial
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Fibocom Dial
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Package/fibocom-dial/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fibocom-dial $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fibo_qmimsg_server $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/multi-pdn-manager $(1)/usr/bin
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,fibocom-dial))
|
||||
@ -1,275 +0,0 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "QMIThread.h"
|
||||
|
||||
#ifdef CONFIG_GOBINET
|
||||
|
||||
// IOCTL to generate a client ID for this service type
|
||||
#define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1
|
||||
|
||||
// IOCTL to get the VIDPID of the device
|
||||
#define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2
|
||||
|
||||
// IOCTL to get the MEID of the device
|
||||
#define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3
|
||||
|
||||
static int GobiNetSendQMI(PQCQMIMSG pRequest)
|
||||
{
|
||||
int ret, fd;
|
||||
|
||||
static int send_count = 0;
|
||||
fd = qmiclientId[pRequest->QMIHdr.QMIType];
|
||||
|
||||
if (fd <= 0) {
|
||||
dbg_time("%s QMIType: %d has no clientID", __func__,
|
||||
pRequest->QMIHdr.QMIType);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
// Always ready to write
|
||||
re_write:
|
||||
if (1 == 1) {
|
||||
ssize_t nwrites =
|
||||
le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR);
|
||||
ret = write(fd, &pRequest->MUXMsg, nwrites);
|
||||
if (ret == nwrites)
|
||||
{
|
||||
ret = 0;
|
||||
send_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
send_count++;
|
||||
dbg_time("%s write=%d, errno: %d (%s) send_count %d", __func__, ret, errno, strerror(errno), send_count);
|
||||
if (send_count < 3)
|
||||
{
|
||||
sleep(1);
|
||||
goto re_write;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int GobiNetGetClientID(const char *qcqmi, UCHAR QMIType)
|
||||
{
|
||||
int ClientId;
|
||||
ClientId = open(qcqmi, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (ClientId == -1) {
|
||||
dbg_time("failed to open %s, errno: %d (%s)", qcqmi, errno,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(ClientId, IOCTL_QMI_GET_SERVICE_FILE, QMIType) != 0) {
|
||||
dbg_time("failed to get ClientID for 0x%02x errno: %d (%s)", QMIType,
|
||||
errno, strerror(errno));
|
||||
close(ClientId);
|
||||
ClientId = 0;
|
||||
}
|
||||
|
||||
dbg_time("%s: QMIType = %d clientid %d", __func__, QMIType, ClientId);
|
||||
|
||||
switch (QMIType) {
|
||||
case QMUX_TYPE_WDS:
|
||||
dbg_time("Get clientWDS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_DMS:
|
||||
dbg_time("Get clientDMS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_NAS:
|
||||
dbg_time("Get clientNAS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_QOS:
|
||||
dbg_time("Get clientQOS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_WMS:
|
||||
dbg_time("Get clientWMS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_PDS:
|
||||
dbg_time("Get clientPDS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_UIM:
|
||||
dbg_time("Get clientUIM = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_WDS_ADMIN:
|
||||
dbg_time("Get clientWDA = %d", ClientId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ClientId;
|
||||
}
|
||||
|
||||
static int GobiNetDeInit(void)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); i++) {
|
||||
if (qmiclientId[i] != 0) {
|
||||
close(qmiclientId[i]);
|
||||
qmiclientId[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static void *GobiNetThread(void *pData)
|
||||
{
|
||||
PROFILE_T *profile = (PROFILE_T *)pData;
|
||||
const char *qcqmi = (const char *)profile->qmichannel;
|
||||
int wait_for_request_quit = 0;
|
||||
dbg_time("%s %d", __func__, __LINE__);
|
||||
if (profile->ipv4_flag)
|
||||
qmiclientId[QMUX_TYPE_WDS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS);
|
||||
if (profile->ipv6_flag)
|
||||
qmiclientId[QMUX_TYPE_WDS_IPV6] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS);
|
||||
qmiclientId[QMUX_TYPE_DMS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_DMS);
|
||||
qmiclientId[QMUX_TYPE_NAS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_NAS);
|
||||
qmiclientId[QMUX_TYPE_UIM] = GobiNetGetClientID(qcqmi, QMUX_TYPE_UIM);
|
||||
// qmiclientId[QMUX_TYPE_WDS_ADMIN] =
|
||||
// GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS_ADMIN);
|
||||
|
||||
//if ((qmiclientId[QMUX_TYPE_WDS] == 0) && (qmiclientId[QMUX_TYPE_WDS_IPV6] == 0)) /*|| (clientWDA == -1)*/ {
|
||||
|
||||
if ((qmiclientId[QMUX_TYPE_DMS] == 0) ||
|
||||
(qmiclientId[QMUX_TYPE_NAS] == 0) ||
|
||||
(qmiclientId[QMUX_TYPE_UIM] == 0) ||
|
||||
(profile->ipv4_flag ? ((qmiclientId[QMUX_TYPE_WDS] == 0) ? 1 : 0):0)||
|
||||
(profile->ipv6_flag ? ((qmiclientId[QMUX_TYPE_WDS_IPV6] == 0) ? 1 : 0):0))
|
||||
{
|
||||
GobiNetDeInit();
|
||||
dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, qcqmi, errno,strerror(errno));
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED);
|
||||
|
||||
while (1) {
|
||||
struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}};
|
||||
int ne, ret, nevents = 1;
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); i++) {
|
||||
if (qmiclientId[i] != 0) {
|
||||
pollfds[nevents].fd = qmiclientId[i];
|
||||
pollfds[nevents].events = POLLIN;
|
||||
pollfds[nevents].revents = 0;
|
||||
nevents++;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1);
|
||||
} while ((ret < 0) && (errno == EINTR));
|
||||
|
||||
if (ret == 0 && wait_for_request_quit) {
|
||||
QmiThreadRecvQMI(
|
||||
NULL); // main thread may pending on QmiThreadSendQMI()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
for (ne = 0; ne < nevents; ne++) {
|
||||
int fd = pollfds[ne].fd;
|
||||
short revents = pollfds[ne].revents;
|
||||
|
||||
if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
||||
dbg_time("%s poll err/hup/inval", __func__);
|
||||
dbg_time("epoll fd = %d, events = 0x%04x", fd, revents);
|
||||
if (fd == qmidevice_control_fd[1]) {
|
||||
} else {
|
||||
}
|
||||
if (revents & (POLLERR | POLLHUP | POLLNVAL))
|
||||
goto __GobiNetThread_quit;
|
||||
}
|
||||
if ((revents & POLLIN) == 0)
|
||||
continue;
|
||||
|
||||
if (fd == qmidevice_control_fd[1]) {
|
||||
int triger_event;
|
||||
if (read(fd, &triger_event, sizeof(triger_event)) ==
|
||||
sizeof(triger_event)) {
|
||||
// DBG("triger_event = 0x%x", triger_event);
|
||||
switch (triger_event) {
|
||||
case RIL_REQUEST_QUIT:
|
||||
goto __GobiNetThread_quit;
|
||||
break;
|
||||
case SIGTERM:
|
||||
wait_for_request_quit = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
ssize_t nreads;
|
||||
static UCHAR QMIBuf[4096];
|
||||
PQCQMIMSG pResponse = (PQCQMIMSG)QMIBuf;
|
||||
|
||||
nreads = read(fd, &pResponse->MUXMsg,
|
||||
sizeof(QMIBuf) - sizeof(QCQMI_HDR));
|
||||
if (nreads <= 0) {
|
||||
dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads,
|
||||
errno, strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]);
|
||||
i++) {
|
||||
if (qmiclientId[i] == fd) {
|
||||
pResponse->QMIHdr.QMIType = i;
|
||||
}
|
||||
}
|
||||
|
||||
pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
|
||||
pResponse->QMIHdr.Length =
|
||||
cpu_to_le16(nreads + sizeof(QCQMI_HDR) - 1);
|
||||
pResponse->QMIHdr.CtlFlags = 0x00;
|
||||
pResponse->QMIHdr.ClientId = fd & 0xFF;
|
||||
|
||||
QmiThreadRecvQMI(pResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__GobiNetThread_quit:
|
||||
GobiNetDeInit();
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
|
||||
QmiThreadRecvQMI(NULL); // main thread may pending on QmiThreadSendQMI()
|
||||
dbg_time("%s exit", __func__);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
static int GobiNetSendQMI(PQCQMIMSG pRequest) { return -1; }
|
||||
static void *GobiNetThread(void *pData)
|
||||
{
|
||||
dbg_time("please set CONFIG_GOBINET");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct qmi_device_ops gobi_qmidev_ops = {
|
||||
.deinit = GobiNetDeInit,
|
||||
.send = GobiNetSendQMI,
|
||||
.read = GobiNetThread,
|
||||
};
|
||||
@ -1,363 +0,0 @@
|
||||
/*===========================================================================
|
||||
|
||||
M P Q C T L. H
|
||||
DESCRIPTION:
|
||||
|
||||
This module contains QMI QCTL module.
|
||||
|
||||
INITIALIZATION AND SEQUENCING REQUIREMENTS:
|
||||
|
||||
Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved.
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef MPQCTL_H
|
||||
#define MPQCTL_H
|
||||
|
||||
#include "MPQMI.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// ================= QMICTL ==================
|
||||
|
||||
// QMICTL Control Flags
|
||||
#define QMICTL_CTL_FLAG_CMD 0x00
|
||||
#define QMICTL_CTL_FLAG_RSP 0x01
|
||||
#define QMICTL_CTL_FLAG_IND 0x02
|
||||
|
||||
#if 0
|
||||
typedef struct _QMICTL_TRANSACTION_ITEM
|
||||
{
|
||||
LIST_ENTRY List;
|
||||
UCHAR TransactionId; // QMICTL transaction id
|
||||
PVOID Context; // Adapter or IocDev
|
||||
PIRP Irp;
|
||||
} QMICTL_TRANSACTION_ITEM, *PQMICTL_TRANSACTION_ITEM;
|
||||
#endif
|
||||
|
||||
typedef struct _QCQMICTL_MSG_HDR {
|
||||
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType;
|
||||
USHORT Length;
|
||||
} __attribute__((packed)) QCQMICTL_MSG_HDR, *PQCQMICTL_MSG_HDR;
|
||||
|
||||
#define QCQMICTL_MSG_HDR_SIZE sizeof(QCQMICTL_MSG_HDR)
|
||||
|
||||
typedef struct _QCQMICTL_MSG_HDR_RESP {
|
||||
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType;
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // 0x02 - result code
|
||||
USHORT TLVLength; // 4
|
||||
USHORT QMUXResult; // QMI_RESULT_SUCCESS
|
||||
// QMI_RESULT_FAILURE
|
||||
USHORT QMUXError; // QMI_ERR_INVALID_ARG
|
||||
// QMI_ERR_NO_MEMORY
|
||||
// QMI_ERR_INTERNAL
|
||||
// QMI_ERR_FAULT
|
||||
} __attribute__((packed)) QCQMICTL_MSG_HDR_RESP, *PQCQMICTL_MSG_HDR_RESP;
|
||||
|
||||
typedef struct _QCQMICTL_MSG {
|
||||
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType;
|
||||
USHORT Length;
|
||||
UCHAR Payload;
|
||||
} __attribute__((packed)) QCQMICTL_MSG, *PQCQMICTL_MSG;
|
||||
|
||||
// TLV Header
|
||||
typedef struct _QCQMICTL_TLV_HDR {
|
||||
UCHAR TLVType;
|
||||
USHORT TLVLength;
|
||||
} __attribute__((packed)) QCQMICTL_TLV_HDR, *PQCQMICTL_TLV_HDR;
|
||||
|
||||
#define QCQMICTL_TLV_HDR_SIZE sizeof(QCQMICTL_TLV_HDR)
|
||||
|
||||
// QMICTL Type
|
||||
#define QMICTL_SET_INSTANCE_ID_REQ 0x0020
|
||||
#define QMICTL_SET_INSTANCE_ID_RESP 0x0020
|
||||
#define QMICTL_GET_VERSION_REQ 0x0021
|
||||
#define QMICTL_GET_VERSION_RESP 0x0021
|
||||
#define QMICTL_GET_CLIENT_ID_REQ 0x0022
|
||||
#define QMICTL_GET_CLIENT_ID_RESP 0x0022
|
||||
#define QMICTL_RELEASE_CLIENT_ID_REQ 0x0023
|
||||
#define QMICTL_RELEASE_CLIENT_ID_RESP 0x0023
|
||||
#define QMICTL_REVOKE_CLIENT_ID_IND 0x0024
|
||||
#define QMICTL_INVALID_CLIENT_ID_IND 0x0025
|
||||
#define QMICTL_SET_DATA_FORMAT_REQ 0x0026
|
||||
#define QMICTL_SET_DATA_FORMAT_RESP 0x0026
|
||||
#define QMICTL_SYNC_REQ 0x0027
|
||||
#define QMICTL_SYNC_RESP 0x0027
|
||||
#define QMICTL_SYNC_IND 0x0027
|
||||
|
||||
#define QMICTL_FLAG_REQUEST 0x00
|
||||
#define QMICTL_FLAG_RESPONSE 0x01
|
||||
#define QMICTL_FLAG_INDICATION 0x02
|
||||
|
||||
// QMICTL Message Definitions
|
||||
|
||||
typedef struct _QMICTL_SET_INSTANCE_ID_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_REQ
|
||||
USHORT Length; // 4
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR Value; // Host-unique QMI instance for this device driver
|
||||
} __attribute__((packed)) QMICTL_SET_INSTANCE_ID_REQ_MSG,
|
||||
*PQMICTL_SET_INSTANCE_ID_REQ_MSG;
|
||||
|
||||
typedef struct _QMICTL_SET_INSTANCE_ID_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult;
|
||||
USHORT QMIError;
|
||||
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLV2Length; // 0x0002
|
||||
USHORT QMI_ID; // Upper byte is assigned by MSM,
|
||||
// lower assigned by host
|
||||
} __attribute__((packed)) QMICTL_SET_INSTANCE_ID_RESP_MSG,
|
||||
*PQMICTL_SET_INSTANCE_ID_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_GET_VERSION_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_GET_VERSION_REQ
|
||||
USHORT Length; // 0
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // var
|
||||
UCHAR QMUXTypes; // List of one byte QMUX_TYPE values
|
||||
// 0xFF returns a list of versions for all
|
||||
// QMUX_TYPEs implemented on the device
|
||||
} __attribute__((packed)) QMICTL_GET_VERSION_REQ_MSG,
|
||||
*PQMICTL_GET_VERSION_REQ_MSG;
|
||||
|
||||
typedef struct _QMUX_TYPE_VERSION_STRUCT {
|
||||
UCHAR QMUXType;
|
||||
USHORT MajorVersion;
|
||||
USHORT MinorVersion;
|
||||
} __attribute__((packed)) QMUX_TYPE_VERSION_STRUCT, *PQMUX_TYPE_VERSION_STRUCT;
|
||||
|
||||
typedef struct _ADDENDUM_VERSION_PREAMBLE {
|
||||
UCHAR LabelLength;
|
||||
UCHAR Label;
|
||||
} __attribute__((packed)) ADDENDUM_VERSION_PREAMBLE,
|
||||
*PADDENDUM_VERSION_PREAMBLE;
|
||||
|
||||
#define QMICTL_GET_VERSION_RSP_TLV_TYPE_VERSION 0x01
|
||||
#define QMICTL_GET_VERSION_RSP_TLV_TYPE_ADD_VERSION 0x10
|
||||
|
||||
typedef struct _QMICTL_GET_VERSION_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_GET_VERSION_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult;
|
||||
USHORT QMIError;
|
||||
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLV2Length; // var
|
||||
UCHAR NumElements; // Num of QMUX_TYPE_VERSION_STRUCT
|
||||
QMUX_TYPE_VERSION_STRUCT TypeVersion[0];
|
||||
} __attribute__((packed)) QMICTL_GET_VERSION_RESP_MSG,
|
||||
*PQMICTL_GET_VERSION_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_GET_CLIENT_ID_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_REQ
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR QMIType; // QMUX type
|
||||
} __attribute__((packed)) QMICTL_GET_CLIENT_ID_REQ_MSG,
|
||||
*PQMICTL_GET_CLIENT_ID_REQ_MSG;
|
||||
|
||||
typedef struct _QMICTL_GET_CLIENT_ID_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult; // result code
|
||||
USHORT QMIError; // error code
|
||||
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLV2Length; // 2
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_GET_CLIENT_ID_RESP_MSG,
|
||||
*PQMICTL_GET_CLIENT_ID_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_RELEASE_CLIENT_ID_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_REQ
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 0x0002
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_RELEASE_CLIENT_ID_REQ_MSG,
|
||||
*PQMICTL_RELEASE_CLIENT_ID_REQ_MSG;
|
||||
|
||||
typedef struct _QMICTL_RELEASE_CLIENT_ID_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult; // result code
|
||||
USHORT QMIError; // error code
|
||||
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLV2Length; // 2
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_RELEASE_CLIENT_ID_RESP_MSG,
|
||||
*PQMICTL_RELEASE_CLIENT_ID_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_REVOKE_CLIENT_ID_IND_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 0x0002
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_REVOKE_CLIENT_ID_IND_MSG,
|
||||
*PQMICTL_REVOKE_CLIENT_ID_IND_MSG;
|
||||
|
||||
typedef struct _QMICTL_INVALID_CLIENT_ID_IND_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 0x0002
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_INVALID_CLIENT_ID_IND_MSG,
|
||||
*PQMICTL_INVALID_CLIENT_ID_IND_MSG;
|
||||
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_REQ
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR DataFormat; // 0-default; 1-QoS hdr present
|
||||
} __attribute__((packed)) QMICTL_SET_DATA_FORMAT_REQ_MSG,
|
||||
*PQMICTL_SET_DATA_FORMAT_REQ_MSG;
|
||||
|
||||
#ifdef QC_IP_MODE
|
||||
#define SET_DATA_FORMAT_TLV_TYPE_LINK_PROTO 0x10
|
||||
#define SET_DATA_FORMAT_LINK_PROTO_ETH 0x0001
|
||||
#define SET_DATA_FORMAT_LINK_PROTO_IP 0x0002
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT {
|
||||
UCHAR TLVType; // Link-Layer Protocol
|
||||
USHORT TLVLength; // 2
|
||||
USHORT LinkProt; // 0x1: ETH; 0x2: IP
|
||||
} QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT, *PQMICTL_SET_DATA_FORMAT_TLV_LINK_PROT;
|
||||
|
||||
#ifdef QCMP_UL_TLP
|
||||
#define SET_DATA_FORMAT_TLV_TYPE_UL_TLP 0x11
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_UL_TLP {
|
||||
UCHAR TLVType; // 0x11, Uplink TLP Setting
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR UlTlpSetting; // 0x0: Disable; 0x01: Enable
|
||||
} QMICTL_SET_DATA_FORMAT_TLV_UL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_UL_TLP;
|
||||
#endif // QCMP_UL_TLP
|
||||
|
||||
#ifdef QCMP_DL_TLP
|
||||
#define SET_DATA_FORMAT_TLV_TYPE_DL_TLP 0x13
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_DL_TLP {
|
||||
UCHAR TLVType; // 0x11, Uplink TLP Setting
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR DlTlpSetting; // 0x0: Disable; 0x01: Enable
|
||||
} QMICTL_SET_DATA_FORMAT_TLV_DL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_DL_TLP;
|
||||
#endif // QCMP_DL_TLP
|
||||
|
||||
#endif // QC_IP_MODE
|
||||
|
||||
#ifdef MP_QCQOS_ENABLED
|
||||
#define SET_DATA_FORMAT_TLV_TYPE_QOS_SETTING 0x12
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING {
|
||||
UCHAR TLVType; // 0x12, QoS setting
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR QosSetting; // 0x0: Disable; 0x01: Enable
|
||||
} QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING,
|
||||
*PQMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING;
|
||||
#endif // MP_QCQOS_ENABLED
|
||||
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult; // result code
|
||||
USHORT QMIError; // error code
|
||||
} __attribute__((packed)) QMICTL_SET_DATA_FORMAT_RESP_MSG,
|
||||
*PQMICTL_SET_DATA_FORMAT_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_SYNC_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_CTL_SYNC_REQ
|
||||
USHORT Length; // 0
|
||||
} __attribute__((packed)) QMICTL_SYNC_REQ_MSG, *PQMICTL_SYNC_REQ_MSG;
|
||||
|
||||
typedef struct _QMICTL_SYNC_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_CTL_SYNC_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult;
|
||||
USHORT QMIError;
|
||||
} __attribute__((packed)) QMICTL_SYNC_RESP_MSG, *PQMICTL_SYNC_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_SYNC_IND_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
|
||||
USHORT Length;
|
||||
} __attribute__((packed)) QMICTL_SYNC_IND_MSG, *PQMICTL_SYNC_IND_MSG;
|
||||
|
||||
typedef struct _QMICTL_MSG {
|
||||
union {
|
||||
// Message Header
|
||||
QCQMICTL_MSG_HDR QMICTLMsgHdr;
|
||||
QCQMICTL_MSG_HDR_RESP QMICTLMsgHdrRsp;
|
||||
|
||||
// QMICTL Message
|
||||
QMICTL_SET_INSTANCE_ID_REQ_MSG SetInstanceIdReq;
|
||||
QMICTL_SET_INSTANCE_ID_RESP_MSG SetInstanceIdRsp;
|
||||
QMICTL_GET_VERSION_REQ_MSG GetVersionReq;
|
||||
QMICTL_GET_VERSION_RESP_MSG GetVersionRsp;
|
||||
QMICTL_GET_CLIENT_ID_REQ_MSG GetClientIdReq;
|
||||
QMICTL_GET_CLIENT_ID_RESP_MSG GetClientIdRsp;
|
||||
QMICTL_RELEASE_CLIENT_ID_REQ_MSG ReleaseClientIdReq;
|
||||
QMICTL_RELEASE_CLIENT_ID_RESP_MSG ReleaseClientIdRsp;
|
||||
QMICTL_REVOKE_CLIENT_ID_IND_MSG RevokeClientIdInd;
|
||||
QMICTL_INVALID_CLIENT_ID_IND_MSG InvalidClientIdInd;
|
||||
QMICTL_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq;
|
||||
QMICTL_SET_DATA_FORMAT_RESP_MSG SetDataFormatRsp;
|
||||
QMICTL_SYNC_REQ_MSG SyncReq;
|
||||
QMICTL_SYNC_RESP_MSG SyncRsp;
|
||||
QMICTL_SYNC_IND_MSG SyncInd;
|
||||
};
|
||||
} __attribute__((packed)) QMICTL_MSG, *PQMICTL_MSG;
|
||||
|
||||
#endif // MPQCTL_H
|
||||
@ -1,287 +0,0 @@
|
||||
/*===========================================================================
|
||||
|
||||
M P Q M I. H
|
||||
DESCRIPTION:
|
||||
|
||||
This module contains forward references to the QMI module.
|
||||
|
||||
INITIALIZATION AND SEQUENCING REQUIREMENTS:
|
||||
|
||||
Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved.
|
||||
===========================================================================*/
|
||||
/*===========================================================================
|
||||
|
||||
EDIT HISTORY FOR FILE
|
||||
$Header: //depot/QMI/win/qcdrivers/ndis/MPQMI.h#3 $
|
||||
|
||||
when who what, where, why
|
||||
-------- --- ----------------------------------------------------------
|
||||
11/20/04 hg Initial version.
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef USBQMI_H
|
||||
#define USBQMI_H
|
||||
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned short USHORT;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef unsigned int ULONG;
|
||||
typedef unsigned long long ULONG64;
|
||||
typedef char *PCHAR;
|
||||
typedef unsigned char *PUCHAR;
|
||||
typedef int *PINT;
|
||||
typedef int BOOL;
|
||||
|
||||
#define TRUE (1 == 1)
|
||||
#define FALSE (1 != 1)
|
||||
|
||||
#define QMICTL_SUPPORTED_MAJOR_VERSION 1
|
||||
#define QMICTL_SUPPORTED_MINOR_VERSION 0
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// ========= USB Control Message ==========
|
||||
|
||||
#define USB_CTL_MSG_TYPE_QMI 0x01
|
||||
|
||||
// USB Control Message
|
||||
typedef struct _QCUSB_CTL_MSG_HDR {
|
||||
UCHAR IFType;
|
||||
} __attribute__((packed)) QCUSB_CTL_MSG_HDR, *PQCUSB_CTL_MSG_HDR;
|
||||
|
||||
#define QCUSB_CTL_MSG_HDR_SIZE sizeof(QCUSB_CTL_MSG_HDR)
|
||||
|
||||
typedef struct _QCUSB_CTL_MSG {
|
||||
UCHAR IFType;
|
||||
UCHAR Message;
|
||||
} __attribute__((packed)) QCUSB_CTL_MSG, *PQCUSB_CTL_MSG;
|
||||
|
||||
#define QCTLV_TYPE_REQUIRED_PARAMETER 0x01
|
||||
#define QCTLV_TYPE_RESULT_CODE 0x02
|
||||
|
||||
// ================= QMI ==================
|
||||
|
||||
// Define QMI Type
|
||||
typedef enum _QMI_SERVICE_TYPE {
|
||||
QMUX_TYPE_CTL = 0x00,
|
||||
QMUX_TYPE_WDS = 0x01,
|
||||
QMUX_TYPE_DMS = 0x02,
|
||||
QMUX_TYPE_NAS = 0x03,
|
||||
QMUX_TYPE_QOS = 0x04,
|
||||
QMUX_TYPE_WMS = 0x05,
|
||||
QMUX_TYPE_PDS = 0x06,
|
||||
QMUX_TYPE_UIM = 0x0B,
|
||||
QMUX_TYPE_WDS_IPV6 = 0x11,
|
||||
QMUX_TYPE_WDS_ADMIN = 0x1A,
|
||||
QMUX_TYPE_MAX = 0xFF,
|
||||
QMUX_TYPE_ALL = 0xFF
|
||||
} QMI_SERVICE_TYPE;
|
||||
|
||||
typedef enum _QMI_RESULT_CODE_TYPE {
|
||||
QMI_RESULT_SUCCESS = 0x0000,
|
||||
QMI_RESULT_FAILURE = 0x0001
|
||||
} QMI_RESULT_CODE_TYPE;
|
||||
|
||||
typedef enum _QMI_ERROR_CODE_TYPE {
|
||||
QMI_ERR_NONE = 0x0000,
|
||||
QMI_ERR_MALFORMED_MSG = 0x0001,
|
||||
QMI_ERR_NO_MEMORY = 0x0002,
|
||||
QMI_ERR_INTERNAL = 0x0003,
|
||||
QMI_ERR_ABORTED = 0x0004,
|
||||
QMI_ERR_CLIENT_IDS_EXHAUSTED = 0x0005,
|
||||
QMI_ERR_UNABORTABLE_TRANSACTION = 0x0006,
|
||||
QMI_ERR_INVALID_CLIENT_ID = 0x0007,
|
||||
QMI_ERR_NO_THRESHOLDS = 0x0008,
|
||||
QMI_ERR_INVALID_HANDLE = 0x0009,
|
||||
QMI_ERR_INVALID_PROFILE = 0x000A,
|
||||
QMI_ERR_INVALID_PINID = 0x000B,
|
||||
QMI_ERR_INCORRECT_PIN = 0x000C,
|
||||
QMI_ERR_NO_NETWORK_FOUND = 0x000D,
|
||||
QMI_ERR_CALL_FAILED = 0x000E,
|
||||
QMI_ERR_OUT_OF_CALL = 0x000F,
|
||||
QMI_ERR_NOT_PROVISIONED = 0x0010,
|
||||
QMI_ERR_MISSING_ARG = 0x0011,
|
||||
QMI_ERR_ARG_TOO_LONG = 0x0013,
|
||||
QMI_ERR_INVALID_TX_ID = 0x0016,
|
||||
QMI_ERR_DEVICE_IN_USE = 0x0017,
|
||||
QMI_ERR_OP_NETWORK_UNSUPPORTED = 0x0018,
|
||||
QMI_ERR_OP_DEVICE_UNSUPPORTED = 0x0019,
|
||||
QMI_ERR_NO_EFFECT = 0x001A,
|
||||
QMI_ERR_NO_FREE_PROFILE = 0x001B,
|
||||
QMI_ERR_INVALID_PDP_TYPE = 0x001C,
|
||||
QMI_ERR_INVALID_TECH_PREF = 0x001D,
|
||||
QMI_ERR_INVALID_PROFILE_TYPE = 0x001E,
|
||||
QMI_ERR_INVALID_SERVICE_TYPE = 0x001F,
|
||||
QMI_ERR_INVALID_REGISTER_ACTION = 0x0020,
|
||||
QMI_ERR_INVALID_PS_ATTACH_ACTION = 0x0021,
|
||||
QMI_ERR_AUTHENTICATION_FAILED = 0x0022,
|
||||
QMI_ERR_PIN_BLOCKED = 0x0023,
|
||||
QMI_ERR_PIN_PERM_BLOCKED = 0x0024,
|
||||
QMI_ERR_SIM_NOT_INITIALIZED = 0x0025,
|
||||
QMI_ERR_MAX_QOS_REQUESTS_IN_USE = 0x0026,
|
||||
QMI_ERR_INCORRECT_FLOW_FILTER = 0x0027,
|
||||
QMI_ERR_NETWORK_QOS_UNAWARE = 0x0028,
|
||||
QMI_ERR_INVALID_QOS_ID = 0x0029,
|
||||
QMI_ERR_INVALID_ID = 0x0029,
|
||||
QMI_ERR_REQUESTED_NUM_UNSUPPORTED = 0x002A,
|
||||
QMI_ERR_INTERFACE_NOT_FOUND = 0x002B,
|
||||
QMI_ERR_FLOW_SUSPENDED = 0x002C,
|
||||
QMI_ERR_INVALID_DATA_FORMAT = 0x002D,
|
||||
QMI_ERR_GENERAL = 0x002E,
|
||||
QMI_ERR_UNKNOWN = 0x002F,
|
||||
QMI_ERR_INVALID_ARG = 0x0030,
|
||||
QMI_ERR_INVALID_INDEX = 0x0031,
|
||||
QMI_ERR_NO_ENTRY = 0x0032,
|
||||
QMI_ERR_DEVICE_STORAGE_FULL = 0x0033,
|
||||
QMI_ERR_DEVICE_NOT_READY = 0x0034,
|
||||
QMI_ERR_NETWORK_NOT_READY = 0x0035,
|
||||
QMI_ERR_CAUSE_CODE = 0x0036,
|
||||
QMI_ERR_MESSAGE_NOT_SENT = 0x0037,
|
||||
QMI_ERR_MESSAGE_DELIVERY_FAILURE = 0x0038,
|
||||
QMI_ERR_INVALID_MESSAGE_ID = 0x0039,
|
||||
QMI_ERR_ENCODING = 0x003A,
|
||||
QMI_ERR_AUTHENTICATION_LOCK = 0x003B,
|
||||
QMI_ERR_INVALID_TRANSITION = 0x003C,
|
||||
QMI_ERR_NOT_A_MCAST_IFACE = 0x003D,
|
||||
QMI_ERR_MAX_MCAST_REQUESTS_IN_USE = 0x003E,
|
||||
QMI_ERR_INVALID_MCAST_HANDLE = 0x003F,
|
||||
QMI_ERR_INVALID_IP_FAMILY_PREF = 0x0040,
|
||||
QMI_ERR_SESSION_INACTIVE = 0x0041,
|
||||
QMI_ERR_SESSION_INVALID = 0x0042,
|
||||
QMI_ERR_SESSION_OWNERSHIP = 0x0043,
|
||||
QMI_ERR_INSUFFICIENT_RESOURCES = 0x0044,
|
||||
QMI_ERR_DISABLED = 0x0045,
|
||||
QMI_ERR_INVALID_OPERATION = 0x0046,
|
||||
QMI_ERR_INVALID_QMI_CMD = 0x0047,
|
||||
QMI_ERR_TPDU_TYPE = 0x0048,
|
||||
QMI_ERR_SMSC_ADDR = 0x0049,
|
||||
QMI_ERR_INFO_UNAVAILABLE = 0x004A,
|
||||
QMI_ERR_SEGMENT_TOO_LONG = 0x004B,
|
||||
QMI_ERR_SEGMENT_ORDER = 0x004C,
|
||||
QMI_ERR_BUNDLING_NOT_SUPPORTED = 0x004D,
|
||||
QMI_ERR_OP_PARTIAL_FAILURE = 0x004E,
|
||||
QMI_ERR_POLICY_MISMATCH = 0x004F,
|
||||
QMI_ERR_SIM_FILE_NOT_FOUND = 0x0050,
|
||||
QMI_ERR_EXTENDED_INTERNAL = 0x0051,
|
||||
QMI_ERR_ACCESS_DENIED = 0x0052,
|
||||
QMI_ERR_HARDWARE_RESTRICTED = 0x0053,
|
||||
QMI_ERR_ACK_NOT_SENT = 0x0054,
|
||||
QMI_ERR_INJECT_TIMEOUT = 0x0055,
|
||||
QMI_ERR_INCOMPATIBLE_STATE = 0x005A,
|
||||
QMI_ERR_FDN_RESTRICT = 0x005B,
|
||||
QMI_ERR_SUPS_FAILURE_CAUSE = 0x005C,
|
||||
QMI_ERR_NO_RADIO = 0x005D,
|
||||
QMI_ERR_NOT_SUPPORTED = 0x005E,
|
||||
QMI_ERR_NO_SUBSCRIPTION = 0x005F,
|
||||
QMI_ERR_CARD_CALL_CONTROL_FAILED = 0x0060,
|
||||
QMI_ERR_NETWORK_ABORTED = 0x0061,
|
||||
QMI_ERR_MSG_BLOCKED = 0x0062,
|
||||
QMI_ERR_INVALID_SESSION_TYPE = 0x0064,
|
||||
QMI_ERR_INVALID_PB_TYPE = 0x0065,
|
||||
QMI_ERR_NO_SIM = 0x0066,
|
||||
QMI_ERR_PB_NOT_READY = 0x0067,
|
||||
QMI_ERR_PIN_RESTRICTION = 0x0068,
|
||||
QMI_ERR_PIN2_RESTRICTION = 0x0069,
|
||||
QMI_ERR_PUK_RESTRICTION = 0x006A,
|
||||
QMI_ERR_PUK2_RESTRICTION = 0x006B,
|
||||
QMI_ERR_PB_ACCESS_RESTRICTED = 0x006C,
|
||||
QMI_ERR_PB_DELETE_IN_PROG = 0x006D,
|
||||
QMI_ERR_PB_TEXT_TOO_LONG = 0x006E,
|
||||
QMI_ERR_PB_NUMBER_TOO_LONG = 0x006F,
|
||||
QMI_ERR_PB_HIDDEN_KEY_RESTRICTION = 0x0070
|
||||
} QMI_ERROR_CODE_TYPE;
|
||||
|
||||
#define QCQMI_CTL_FLAG_SERVICE 0x80
|
||||
#define QCQMI_CTL_FLAG_CTL_POINT 0x00
|
||||
|
||||
typedef struct _QCQMI_HDR {
|
||||
UCHAR IFType;
|
||||
USHORT Length;
|
||||
UCHAR CtlFlags; // reserved
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QCQMI_HDR, *PQCQMI_HDR;
|
||||
|
||||
#define QCQMI_HDR_SIZE (sizeof(QCQMI_HDR) - 1)
|
||||
|
||||
typedef struct _QCQMI {
|
||||
UCHAR IFType;
|
||||
USHORT Length;
|
||||
UCHAR CtlFlags; // reserved
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
UCHAR SDU;
|
||||
} __attribute__((packed)) QCQMI, *PQCQMI;
|
||||
|
||||
typedef struct _QMI_SERVICE_VERSION {
|
||||
USHORT Major;
|
||||
USHORT Minor;
|
||||
USHORT AddendumMajor;
|
||||
USHORT AddendumMinor;
|
||||
} __attribute__((packed)) QMI_SERVICE_VERSION, *PQMI_SERVICE_VERSION;
|
||||
|
||||
// ================= QMUX ==================
|
||||
|
||||
#define QMUX_MSG_OVERHEAD_BYTES 4 // Type(USHORT) Length(USHORT) -- header
|
||||
|
||||
#define QMUX_BROADCAST_CID 0xFF
|
||||
|
||||
typedef struct _QCQMUX_HDR {
|
||||
UCHAR CtlFlags; // 0: single QMUX Msg; 1:
|
||||
USHORT TransactionId;
|
||||
} __attribute__((packed)) QCQMUX_HDR, *PQCQMUX_HDR;
|
||||
|
||||
typedef struct _QCQMUX {
|
||||
UCHAR CtlFlags; // 0: single QMUX Msg; 1:
|
||||
USHORT TransactionId;
|
||||
UCHAR Message; // Type(2), Length(2), Value
|
||||
} __attribute__((packed)) QCQMUX, *PQCQMUX;
|
||||
|
||||
#define QCQMUX_HDR_SIZE sizeof(QCQMUX_HDR)
|
||||
|
||||
typedef struct _QCQMUX_MSG_HDR {
|
||||
USHORT Type;
|
||||
USHORT Length;
|
||||
} __attribute__((packed)) QCQMUX_MSG_HDR, *PQCQMUX_MSG_HDR;
|
||||
|
||||
#define QCQMUX_MSG_HDR_SIZE sizeof(QCQMUX_MSG_HDR)
|
||||
|
||||
typedef struct _QCQMUX_MSG_HDR_RESP {
|
||||
USHORT Type;
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // 0x02 - result code
|
||||
USHORT TLVLength; // 4
|
||||
USHORT QMUXResult; // QMI_RESULT_SUCCESS
|
||||
// QMI_RESULT_FAILURE
|
||||
USHORT QMUXError; // QMI_ERR_INVALID_ARG
|
||||
// QMI_ERR_NO_MEMORY
|
||||
// QMI_ERR_INTERNAL
|
||||
// QMI_ERR_FAULT
|
||||
} __attribute__((packed)) QCQMUX_MSG_HDR_RESP, *PQCQMUX_MSG_HDR_RESP;
|
||||
|
||||
typedef struct _QCQMUX_TLV {
|
||||
UCHAR Type;
|
||||
USHORT Length;
|
||||
UCHAR Value;
|
||||
} __attribute__((packed)) QCQMUX_TLV, *PQCQMUX_TLV;
|
||||
|
||||
typedef struct _QMI_TLV_HDR {
|
||||
UCHAR TLVType;
|
||||
USHORT TLVLength;
|
||||
} __attribute__((packed)) QMI_TLV_HDR, *PQMI_TLV_HDR;
|
||||
|
||||
// QMUX Message Definitions -- QMI SDU
|
||||
#define QMUX_CTL_FLAG_SINGLE_MSG 0x00
|
||||
#define QMUX_CTL_FLAG_COMPOUND_MSG 0x01
|
||||
#define QMUX_CTL_FLAG_TYPE_CMD 0x00
|
||||
#define QMUX_CTL_FLAG_TYPE_RSP 0x02
|
||||
#define QMUX_CTL_FLAG_TYPE_IND 0x04
|
||||
#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01
|
||||
#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // USBQMI_H
|
||||
@ -1,437 +0,0 @@
|
||||
#include "QMIThread.h"
|
||||
static char line[1024];
|
||||
static pthread_mutex_t dumpQMIMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#undef dbg
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (strlen(line) < sizeof(line)) \
|
||||
snprintf(&line[strlen(line)], sizeof(line) - strlen(line), format, \
|
||||
##arg); \
|
||||
} while (0)
|
||||
|
||||
PQMI_TLV_HDR GetTLV(PQCQMUX_MSG_HDR pQMUXMsgHdr, int TLVType);
|
||||
|
||||
typedef struct {
|
||||
UINT type;
|
||||
const char *name;
|
||||
} QMI_NAME_T;
|
||||
|
||||
#define qmi_name_item(type) \
|
||||
{ \
|
||||
type, #type \
|
||||
}
|
||||
|
||||
static const QMI_NAME_T qmux_ctl_QMICTLType[] = {
|
||||
// QMICTL Type
|
||||
qmi_name_item(QMICTL_SET_INSTANCE_ID_REQ), // 0x0020
|
||||
qmi_name_item(QMICTL_SET_INSTANCE_ID_RESP), // 0x0020
|
||||
qmi_name_item(QMICTL_GET_VERSION_REQ), // 0x0021
|
||||
qmi_name_item(QMICTL_GET_VERSION_RESP), // 0x0021
|
||||
qmi_name_item(QMICTL_GET_CLIENT_ID_REQ), // 0x0022
|
||||
qmi_name_item(QMICTL_GET_CLIENT_ID_RESP), // 0x0022
|
||||
qmi_name_item(QMICTL_RELEASE_CLIENT_ID_REQ), // 0x0023
|
||||
qmi_name_item(QMICTL_RELEASE_CLIENT_ID_RESP), // 0x0023
|
||||
qmi_name_item(QMICTL_REVOKE_CLIENT_ID_IND), // 0x0024
|
||||
qmi_name_item(QMICTL_INVALID_CLIENT_ID_IND), // 0x0025
|
||||
qmi_name_item(QMICTL_SET_DATA_FORMAT_REQ), // 0x0026
|
||||
qmi_name_item(QMICTL_SET_DATA_FORMAT_RESP), // 0x0026
|
||||
qmi_name_item(QMICTL_SYNC_REQ), // 0x0027
|
||||
qmi_name_item(QMICTL_SYNC_RESP), // 0x0027
|
||||
qmi_name_item(QMICTL_SYNC_IND), // 0x0027
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_CtlFlags[] = {
|
||||
qmi_name_item(QMUX_CTL_FLAG_TYPE_CMD),
|
||||
qmi_name_item(QMUX_CTL_FLAG_TYPE_RSP),
|
||||
qmi_name_item(QMUX_CTL_FLAG_TYPE_IND),
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_wds_Type[] = {
|
||||
qmi_name_item(QMIWDS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||
qmi_name_item(QMIWDS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||
qmi_name_item(QMIWDS_EVENT_REPORT_IND), // 0x0001
|
||||
qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_REQ), // 0x0020
|
||||
qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_RESP), // 0x0020
|
||||
qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_REQ), // 0x0021
|
||||
qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_RESP), // 0x0021
|
||||
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_REQ), // 0x0022
|
||||
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_RESP), // 0x0022
|
||||
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_IND), // 0x0022
|
||||
qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ), // 0x0023
|
||||
qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP), // 0x0023
|
||||
qmi_name_item(QMIWDS_GET_PKT_STATISTICS_REQ), // 0x0024
|
||||
qmi_name_item(QMIWDS_GET_PKT_STATISTICS_RESP), // 0x0024
|
||||
//begin modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610
|
||||
qmi_name_item(QMIWDS_CREATE_PROFILE_SETTINGS_REQ), // 0x0027
|
||||
qmi_name_item(QMIWDS_CREATE_PROFILE_SETTINGS_RESP), // 0x0027
|
||||
//end modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610
|
||||
qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ), // 0x0028
|
||||
qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_RESP), // 0x0028
|
||||
qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_REQ), // 0x002B
|
||||
qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_RESP), // 0x002BD
|
||||
qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_REQ), // 0x002C
|
||||
qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_RESP), // 0x002C
|
||||
qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_REQ), // 0x002D
|
||||
qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_RESP), // 0x002D
|
||||
qmi_name_item(QMIWDS_GET_MIP_MODE_REQ), // 0x002F
|
||||
qmi_name_item(QMIWDS_GET_MIP_MODE_RESP), // 0x002F
|
||||
qmi_name_item(QMIWDS_GET_DATA_BEARER_REQ), // 0x0037
|
||||
qmi_name_item(QMIWDS_GET_DATA_BEARER_RESP), // 0x0037
|
||||
qmi_name_item(QMIWDS_DUN_CALL_INFO_REQ), // 0x0038
|
||||
qmi_name_item(QMIWDS_DUN_CALL_INFO_RESP), // 0x0038
|
||||
qmi_name_item(QMIWDS_DUN_CALL_INFO_IND), // 0x0038
|
||||
qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ), // 0x004D
|
||||
qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP), // 0x004D
|
||||
qmi_name_item(QMIWDS_SET_AUTO_CONNECT_REQ), // 0x0051
|
||||
qmi_name_item(QMIWDS_SET_AUTO_CONNECT_RESP), // 0x0051
|
||||
qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_REQ), // 0x00A2
|
||||
qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_RESP), // 0x00A2
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_dms_Type[] = {
|
||||
// ======================= DMS ==============================
|
||||
qmi_name_item(QMIDMS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||
qmi_name_item(QMIDMS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||
qmi_name_item(QMIDMS_EVENT_REPORT_IND), // 0x0001
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_CAP_REQ), // 0x0020
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_CAP_RESP), // 0x0020
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_MFR_REQ), // 0x0021
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_MFR_RESP), // 0x0021
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_REQ), // 0x0022
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_RESP), // 0x0022
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_REQ), // 0x0023
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_RESP), // 0x0023
|
||||
qmi_name_item(QMIDMS_GET_MSISDN_REQ), // 0x0024
|
||||
qmi_name_item(QMIDMS_GET_MSISDN_RESP), // 0x0024
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ), // 0x0025
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP), // 0x0025
|
||||
qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_REQ), // 0x0027
|
||||
qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_RESP), // 0x0027
|
||||
qmi_name_item(QMIDMS_UIM_VERIFY_PIN_REQ), // 0x0028
|
||||
qmi_name_item(QMIDMS_UIM_VERIFY_PIN_RESP), // 0x0028
|
||||
qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_REQ), // 0x0029
|
||||
qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_RESP), // 0x0029
|
||||
qmi_name_item(QMIDMS_UIM_CHANGE_PIN_REQ), // 0x002A
|
||||
qmi_name_item(QMIDMS_UIM_CHANGE_PIN_RESP), // 0x002A
|
||||
qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_REQ), // 0x002B
|
||||
qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_RESP), // 0x002B
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_REQ), // 0x002C
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_RESP), // 0x002C
|
||||
qmi_name_item(QMIDMS_GET_OPERATING_MODE_REQ), // 0x002D
|
||||
qmi_name_item(QMIDMS_GET_OPERATING_MODE_RESP), // 0x002D
|
||||
qmi_name_item(QMIDMS_SET_OPERATING_MODE_REQ), // 0x002E
|
||||
qmi_name_item(QMIDMS_SET_OPERATING_MODE_RESP), // 0x002E
|
||||
qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_REQ), // 0x0031
|
||||
qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_RESP), // 0x0031
|
||||
qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_REQ), // 0x0032
|
||||
qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_RESP), // 0x0032
|
||||
qmi_name_item(QMIDMS_ACTIVATE_MANUAL_REQ), // 0x0033
|
||||
qmi_name_item(QMIDMS_ACTIVATE_MANUAL_RESP), // 0x0033
|
||||
qmi_name_item(QMIDMS_UIM_GET_ICCID_REQ), // 0x003C
|
||||
qmi_name_item(QMIDMS_UIM_GET_ICCID_RESP), // 0x003C
|
||||
qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_REQ), // 0x0040
|
||||
qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_RESP), // 0x0040
|
||||
qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_REQ), // 0x0041
|
||||
qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_RESP), // 0x0041
|
||||
qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_REQ), // 0x0042
|
||||
qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_RESP), // 0x0042
|
||||
qmi_name_item(QMIDMS_UIM_GET_IMSI_REQ), // 0x0043
|
||||
qmi_name_item(QMIDMS_UIM_GET_IMSI_RESP), // 0x0043
|
||||
qmi_name_item(QMIDMS_UIM_GET_STATE_REQ), // 0x0044
|
||||
qmi_name_item(QMIDMS_UIM_GET_STATE_RESP), // 0x0044
|
||||
qmi_name_item(QMIDMS_GET_BAND_CAP_REQ), // 0x0045
|
||||
qmi_name_item(QMIDMS_GET_BAND_CAP_RESP), // 0x0045
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_nas_Type[] = {
|
||||
// ======================= NAS ==============================
|
||||
qmi_name_item(QMINAS_SET_EVENT_REPORT_REQ), // 0x0002
|
||||
qmi_name_item(QMINAS_SET_EVENT_REPORT_RESP), // 0x0002
|
||||
qmi_name_item(QMINAS_EVENT_REPORT_IND), // 0x0002
|
||||
qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_REQ), // 0x0020
|
||||
qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_RESP), // 0x0020
|
||||
qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_REQ), // 0x0021
|
||||
qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_RESP), // 0x0021
|
||||
qmi_name_item(QMINAS_INITIATE_NW_REGISTER_REQ), // 0x0022
|
||||
qmi_name_item(QMINAS_INITIATE_NW_REGISTER_RESP), // 0x0022
|
||||
qmi_name_item(QMINAS_INITIATE_ATTACH_REQ), // 0x0023
|
||||
qmi_name_item(QMINAS_INITIATE_ATTACH_RESP), // 0x0023
|
||||
qmi_name_item(QMINAS_GET_SERVING_SYSTEM_REQ), // 0x0024
|
||||
qmi_name_item(QMINAS_GET_SERVING_SYSTEM_RESP), // 0x0024
|
||||
qmi_name_item(QMINAS_SERVING_SYSTEM_IND), // 0x0024
|
||||
qmi_name_item(QMINAS_GET_HOME_NETWORK_REQ), // 0x0025
|
||||
qmi_name_item(QMINAS_GET_HOME_NETWORK_RESP), // 0x0025
|
||||
qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_REQ), // 0x0026
|
||||
qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_RESP), // 0x0026
|
||||
qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_REQ), // 0x0027
|
||||
qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_RESP), // 0x0027
|
||||
qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_REQ), // 0x0028
|
||||
qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_RESP), // 0x0028
|
||||
qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_REQ), // 0x0029
|
||||
qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_RESP), // 0x0029
|
||||
qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_REQ), // 0x002A
|
||||
qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_RESP), // 0x002A
|
||||
qmi_name_item(QMINAS_GET_RF_BAND_INFO_REQ), // 0x0031
|
||||
qmi_name_item(QMINAS_GET_RF_BAND_INFO_RESP), // 0x0031
|
||||
qmi_name_item(QMINAS_GET_PLMN_NAME_REQ), // 0x0044
|
||||
qmi_name_item(QMINAS_GET_PLMN_NAME_RESP), // 0x0044
|
||||
qmi_name_item(FIBO_PACKET_TRANSFER_START_IND), // 0X100
|
||||
qmi_name_item(FIBO_PACKET_TRANSFER_END_IND), // 0X101
|
||||
qmi_name_item(QMINAS_GET_SYS_INFO_REQ), // 0x004D
|
||||
qmi_name_item(QMINAS_GET_SYS_INFO_RESP), // 0x004D
|
||||
qmi_name_item(QMINAS_SYS_INFO_IND), // 0x004D
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_wms_Type[] = {
|
||||
// ======================= WMS ==============================
|
||||
qmi_name_item(QMIWMS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||
qmi_name_item(QMIWMS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||
qmi_name_item(QMIWMS_EVENT_REPORT_IND), // 0x0001
|
||||
qmi_name_item(QMIWMS_RAW_SEND_REQ), // 0x0020
|
||||
qmi_name_item(QMIWMS_RAW_SEND_RESP), // 0x0020
|
||||
qmi_name_item(QMIWMS_RAW_WRITE_REQ), // 0x0021
|
||||
qmi_name_item(QMIWMS_RAW_WRITE_RESP), // 0x0021
|
||||
qmi_name_item(QMIWMS_RAW_READ_REQ), // 0x0022
|
||||
qmi_name_item(QMIWMS_RAW_READ_RESP), // 0x0022
|
||||
qmi_name_item(QMIWMS_MODIFY_TAG_REQ), // 0x0023
|
||||
qmi_name_item(QMIWMS_MODIFY_TAG_RESP), // 0x0023
|
||||
qmi_name_item(QMIWMS_DELETE_REQ), // 0x0024
|
||||
qmi_name_item(QMIWMS_DELETE_RESP), // 0x0024
|
||||
qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_REQ), // 0x0030
|
||||
qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_RESP), // 0x0030
|
||||
qmi_name_item(QMIWMS_LIST_MESSAGES_REQ), // 0x0031
|
||||
qmi_name_item(QMIWMS_LIST_MESSAGES_RESP), // 0x0031
|
||||
qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_REQ), // 0x0034
|
||||
qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_RESP), // 0x0034
|
||||
qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_REQ), // 0x0035
|
||||
qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_RESP), // 0x0035
|
||||
qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_REQ), // 0x0036
|
||||
qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_RESP), // 0x0036
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_wds_admin_Type[] = {
|
||||
qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ), // 0x0020
|
||||
qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_RESP), // 0x0020
|
||||
qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_REQ), // 0x0021
|
||||
qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_RESP), // 0x0021
|
||||
qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ), // 0x002B
|
||||
qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP), // 0x002B
|
||||
qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ), // 0x002C
|
||||
qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP), // 0x002C
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_uim_Type[] = {
|
||||
qmi_name_item(QMIUIM_READ_TRANSPARENT_REQ), // 0x0020
|
||||
qmi_name_item(QMIUIM_READ_TRANSPARENT_RESP), // 0x0020
|
||||
qmi_name_item(QMIUIM_READ_TRANSPARENT_IND), // 0x0020
|
||||
qmi_name_item(QMIUIM_READ_RECORD_REQ), // 0x0021
|
||||
qmi_name_item(QMIUIM_READ_RECORD_RESP), // 0x0021
|
||||
qmi_name_item(QMIUIM_READ_RECORD_IND), // 0x0021
|
||||
qmi_name_item(QMIUIM_WRITE_TRANSPARENT_REQ), // 0x0022
|
||||
qmi_name_item(QMIUIM_WRITE_TRANSPARENT_RESP), // 0x0022
|
||||
qmi_name_item(QMIUIM_WRITE_TRANSPARENT_IND), // 0x0022
|
||||
qmi_name_item(QMIUIM_WRITE_RECORD_REQ), // 0x0023
|
||||
qmi_name_item(QMIUIM_WRITE_RECORD_RESP), // 0x0023
|
||||
qmi_name_item(QMIUIM_WRITE_RECORD_IND), // 0x0023
|
||||
qmi_name_item(QMIUIM_SET_PIN_PROTECTION_REQ), // 0x0025
|
||||
qmi_name_item(QMIUIM_SET_PIN_PROTECTION_RESP), // 0x0025
|
||||
qmi_name_item(QMIUIM_SET_PIN_PROTECTION_IND), // 0x0025
|
||||
qmi_name_item(QMIUIM_VERIFY_PIN_REQ), // 0x0026
|
||||
qmi_name_item(QMIUIM_VERIFY_PIN_RESP), // 0x0026
|
||||
qmi_name_item(QMIUIM_VERIFY_PIN_IND), // 0x0026
|
||||
qmi_name_item(QMIUIM_UNBLOCK_PIN_REQ), // 0x0027
|
||||
qmi_name_item(QMIUIM_UNBLOCK_PIN_RESP), // 0x0027
|
||||
qmi_name_item(QMIUIM_UNBLOCK_PIN_IND), // 0x0027
|
||||
qmi_name_item(QMIUIM_CHANGE_PIN_REQ), // 0x0028
|
||||
qmi_name_item(QMIUIM_CHANGE_PIN_RESP), // 0x0028
|
||||
qmi_name_item(QMIUIM_CHANGE_PIN_IND), // 0x0028
|
||||
qmi_name_item(QMIUIM_DEPERSONALIZATION_REQ), // 0x0029
|
||||
qmi_name_item(QMIUIM_DEPERSONALIZATION_RESP), // 0x0029
|
||||
qmi_name_item(QMIUIM_EVENT_REG_REQ), // 0x002E
|
||||
qmi_name_item(QMIUIM_EVENT_REG_RESP), // 0x002E
|
||||
qmi_name_item(QMIUIM_GET_CARD_STATUS_REQ), // 0x002F
|
||||
qmi_name_item(QMIUIM_GET_CARD_STATUS_RESP), // 0x002F
|
||||
qmi_name_item(QMIUIM_STATUS_CHANGE_IND), // 0x0032
|
||||
};
|
||||
|
||||
static const char *qmi_name_get(const QMI_NAME_T *table, size_t size, int type,
|
||||
const char *tag)
|
||||
{
|
||||
static char unknow[40];
|
||||
size_t i;
|
||||
|
||||
if (qmux_CtlFlags == table) {
|
||||
if (!strcmp(tag, "_REQ"))
|
||||
tag = "_CMD";
|
||||
else if (!strcmp(tag, "_RESP"))
|
||||
tag = "_RSP";
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (table[i].type == (UINT)type) {
|
||||
if (!tag || (strstr(table[i].name, tag)))
|
||||
return table[i].name;
|
||||
}
|
||||
}
|
||||
sprintf(unknow, "unknow_%x", type);
|
||||
return unknow;
|
||||
}
|
||||
|
||||
#define QMI_NAME(table, type) \
|
||||
qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, 0)
|
||||
#define QMUX_NAME(table, type, tag) \
|
||||
qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, tag)
|
||||
|
||||
void dump_tlv(PQCQMUX_MSG_HDR pQMUXMsgHdr)
|
||||
{
|
||||
int TLVFind = 0;
|
||||
int i;
|
||||
// dbg("QCQMUX_TLV-----------------------------------\n");
|
||||
// dbg("{Type,\tLength,\tValue}\n");
|
||||
|
||||
while (1) {
|
||||
PQMI_TLV_HDR TLVHdr = GetTLV(pQMUXMsgHdr, 0x1000 + (++TLVFind));
|
||||
if (TLVHdr == NULL)
|
||||
break;
|
||||
|
||||
// if ((TLVHdr->TLVType == 0x02) && ((USHORT *)(TLVHdr+1))[0])
|
||||
{
|
||||
dbg("{%02x,\t%04x,\t", TLVHdr->TLVType,
|
||||
le16_to_cpu(TLVHdr->TLVLength));
|
||||
for (i = 0; i < le16_to_cpu(TLVHdr->TLVLength); i++) {
|
||||
dbg("%02x ", ((UCHAR *)(TLVHdr + 1))[i]);
|
||||
}
|
||||
dbg("}\n");
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
void dump_ctl(PQCQMICTL_MSG_HDR CTLHdr)
|
||||
{
|
||||
const char *tag;
|
||||
|
||||
// dbg("QCQMICTL_MSG--------------------------------------------\n");
|
||||
// dbg("CtlFlags: %02x\t\t%s\n", CTLHdr->CtlFlags,
|
||||
// QMI_NAME(qmi_ctl_CtlFlags, CTLHdr->CtlFlags));
|
||||
dbg("TransactionId: %02x\n", CTLHdr->TransactionId);
|
||||
switch (CTLHdr->CtlFlags) {
|
||||
case QMICTL_FLAG_REQUEST:
|
||||
tag = "_REQ";
|
||||
break;
|
||||
case QMICTL_FLAG_RESPONSE:
|
||||
tag = "_RESP";
|
||||
break;
|
||||
case QMICTL_FLAG_INDICATION:
|
||||
tag = "_IND";
|
||||
break;
|
||||
default:
|
||||
tag = 0;
|
||||
break;
|
||||
}
|
||||
dbg("QMICTLType: %04x\t%s\n", le16_to_cpu(CTLHdr->QMICTLType),
|
||||
QMUX_NAME(qmux_ctl_QMICTLType, le16_to_cpu(CTLHdr->QMICTLType), tag));
|
||||
dbg("Length: %04x\n", le16_to_cpu(CTLHdr->Length));
|
||||
|
||||
dump_tlv((PQCQMUX_MSG_HDR)(&CTLHdr->QMICTLType));
|
||||
}
|
||||
|
||||
int dump_qmux(QMI_SERVICE_TYPE serviceType, PQCQMUX_HDR QMUXHdr)
|
||||
{
|
||||
PQCQMUX_MSG_HDR QMUXMsgHdr = (PQCQMUX_MSG_HDR)(QMUXHdr + 1);
|
||||
CHAR *tag;
|
||||
|
||||
// dbg("QCQMUX--------------------------------------------\n");
|
||||
switch (QMUXHdr->CtlFlags & QMUX_CTL_FLAG_MASK_TYPE) {
|
||||
case QMUX_CTL_FLAG_TYPE_CMD:
|
||||
tag = "_REQ";
|
||||
break;
|
||||
case QMUX_CTL_FLAG_TYPE_RSP:
|
||||
tag = "_RESP";
|
||||
break;
|
||||
case QMUX_CTL_FLAG_TYPE_IND:
|
||||
tag = "_IND";
|
||||
break;
|
||||
default:
|
||||
tag = 0;
|
||||
break;
|
||||
}
|
||||
// dbg("CtlFlags: %02x\t\t%s\n", QMUXHdr->CtlFlags,
|
||||
// QMUX_NAME(qmux_CtlFlags, QMUXHdr->CtlFlags, tag));
|
||||
dbg("TransactionId: %04x\n", le16_to_cpu(QMUXHdr->TransactionId));
|
||||
|
||||
// dbg("QCQMUX_MSG_HDR-----------------------------------\n");
|
||||
switch (serviceType) {
|
||||
case QMUX_TYPE_DMS:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_dms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_NAS:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_nas_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_WDS:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_wds_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_WMS:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_wms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_WDS_ADMIN:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_wds_admin_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_UIM:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_uim_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_PDS:
|
||||
case QMUX_TYPE_QOS:
|
||||
case QMUX_TYPE_CTL:
|
||||
default:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
"PDS/QOS/CTL/unknown!");
|
||||
break;
|
||||
}
|
||||
dbg("Length: %04x\n", le16_to_cpu(QMUXMsgHdr->Length));
|
||||
|
||||
dump_tlv(QMUXMsgHdr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dump_qmi(void *dataBuffer, int dataLen)
|
||||
{
|
||||
PQCQMI_HDR QMIHdr = (PQCQMI_HDR)dataBuffer;
|
||||
PQCQMUX_HDR QMUXHdr = (PQCQMUX_HDR)(QMIHdr + 1);
|
||||
PQCQMICTL_MSG_HDR CTLHdr = (PQCQMICTL_MSG_HDR)(QMIHdr + 1);
|
||||
|
||||
int i;
|
||||
|
||||
if (!debug_qmi)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&dumpQMIMutex);
|
||||
line[0] = 0;
|
||||
for (i = 0; i < dataLen; i++) {
|
||||
dbg("%02x ", ((unsigned char *)dataBuffer)[i]);
|
||||
}
|
||||
dbg_time("%s", line);
|
||||
line[0] = 0;
|
||||
|
||||
// dbg("QCQMI_HDR-----------------------------------------");
|
||||
// dbg("IFType: %02x\t\t%s", QMIHdr->IFType,
|
||||
// QMI_NAME(qmi_IFType, QMIHdr->IFType)); dbg("Length: %04x",
|
||||
// le16_to_cpu(QMIHdr->Length)); dbg("CtlFlags: %02x\t\t%s",
|
||||
// QMIHdr->CtlFlags, QMI_NAME(qmi_CtlFlags, QMIHdr->CtlFlags));
|
||||
// dbg("QMIType: %02x\t\t%s", QMIHdr->QMIType, QMI_NAME(qmi_QMIType,
|
||||
// QMIHdr->QMIType)); dbg("ClientId: %02x", QMIHdr->ClientId);
|
||||
|
||||
if (QMIHdr->QMIType == QMUX_TYPE_CTL) {
|
||||
dump_ctl(CTLHdr);
|
||||
} else {
|
||||
dump_qmux(QMIHdr->QMIType, QMUXHdr);
|
||||
}
|
||||
dbg_time("%s", line);
|
||||
pthread_mutex_unlock(&dumpQMIMutex);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,42 +0,0 @@
|
||||
ifneq ($(CROSS_COMPILE),)
|
||||
CROSS-COMPILE:=$(CROSS_COMPILE)
|
||||
endif
|
||||
|
||||
CFLAGS += -DGHT_FEATURE_PCIE_AUTO
|
||||
|
||||
ifeq ($(CC),cc)
|
||||
CC:=$(CROSS-COMPILE)gcc
|
||||
endif
|
||||
LD:=$(CROSS-COMPILE)ld
|
||||
|
||||
SRC=QmiWwanCM.c GobiNetCM.c main.c MPQMUX.c QMIThread.c util.c qmap_bridge_mode.c query_pcie_mode.c
|
||||
|
||||
FB_DHCP=udhcpc.c
|
||||
|
||||
FIBO_PROXY_SRC=fibo_qmimsg_server.c
|
||||
|
||||
LIBMNL=libmnl/ifutils.c libmnl/attr.c libmnl/callback.c libmnl/nlmsg.c libmnl/socket.c
|
||||
FB_NDHCP=udhcpc_netlink.c
|
||||
FB_NDHCP+=${LIBMNL}
|
||||
|
||||
release: clean
|
||||
$(CC) $(CFLAGS) -Wall -s ${SRC} ${FB_NDHCP} -o fibocom-dial -lpthread -ldl
|
||||
$(CC) -Wall -s multi-pdn-manager.c query_pcie_mode.c util.c -o multi-pdn-manager -lpthread -ldl
|
||||
$(CC) -Wall -s ${FIBO_PROXY_SRC} -o fibo_qmimsg_server -lpthread -ldl
|
||||
|
||||
dhcp: clean
|
||||
$(CC) $(CFLAGS) -Wall -s ${SRC} ${FB_DHCP} -o fibocom-dial -lpthread -ldl
|
||||
$(CC) -Wall -s multi-pdn-manager.c query_pcie_mode.c util.c -o multi-pdn-manager -lpthread -ldl
|
||||
$(CC) -Wall -s ${FIBO_PROXY_SRC} -o fibo_qmimsg_server -lpthread -ldl
|
||||
|
||||
ndhcp: clean
|
||||
$(CC) $(CFLAGS) -Wall -s ${SRC} ${FB_NDHCP} -o fibocom-dial -lpthread -ldl
|
||||
$(CC) -Wall -s multi-pdn-manager.c query_pcie_mode.cutil.c -o multi-pdn-manager -lpthread -ldl
|
||||
$(CC) -Wall -s ${FIBO_PROXY_SRC} -o fibo_qmimsg_server -lpthread -ldl
|
||||
|
||||
qmi-proxy:
|
||||
$(CC) -Wall -s fibo-qmi-proxy.c -o fibo-qmi-proxy -lpthread -ldl
|
||||
|
||||
clean:
|
||||
rm -rf fibocom-dial *~ multi-pdn-manager fibo_qmimsg_server
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,260 +0,0 @@
|
||||
#ifndef __QMI_THREAD_H__
|
||||
#define __QMI_THREAD_H__
|
||||
|
||||
#define CONFIG_GOBINET
|
||||
#define CONFIG_QMIWWAN
|
||||
#define CONFIG_SIM
|
||||
#define CONFIG_APN
|
||||
#define CONFIG_VERSION
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
#define CONFIG_IMSI_ICCID
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
#define CONFIG_DEFAULT_PDP 1
|
||||
#define CONFIG_DEFAULT_PDPINDEX 1
|
||||
//#define CONFIG_IMSI_ICCID
|
||||
|
||||
#define CONFIG_RESET_RADIO \
|
||||
(45) // Reset Radiao(AT+CFUN=4,AT+CFUN=1) when cann not register network or
|
||||
// setup data call in 45 seconds
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "MPQCTL.h"
|
||||
#include "MPQMI.h"
|
||||
#include "MPQMUX.h"
|
||||
|
||||
#define DEVICE_CLASS_UNKNOWN 0
|
||||
#define DEVICE_CLASS_CDMA 1
|
||||
#define DEVICE_CLASS_GSM 2
|
||||
|
||||
#define WWAN_DATA_CLASS_NONE 0x00000000
|
||||
#define WWAN_DATA_CLASS_GPRS 0x00000001
|
||||
#define WWAN_DATA_CLASS_EDGE 0x00000002 /* EGPRS */
|
||||
#define WWAN_DATA_CLASS_UMTS 0x00000004
|
||||
#define WWAN_DATA_CLASS_HSDPA 0x00000008
|
||||
#define WWAN_DATA_CLASS_HSUPA 0x00000010
|
||||
#define WWAN_DATA_CLASS_LTE 0x00000020
|
||||
//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605
|
||||
#define WWAN_DATA_CLASS_5G 0x00000040
|
||||
//end modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605
|
||||
#define WWAN_DATA_CLASS_1XRTT 0x00010000
|
||||
#define WWAN_DATA_CLASS_1XEVDO 0x00020000
|
||||
#define WWAN_DATA_CLASS_1XEVDO_REVA 0x00040000
|
||||
#define WWAN_DATA_CLASS_1XEVDV 0x00080000
|
||||
#define WWAN_DATA_CLASS_3XRTT 0x00100000
|
||||
#define WWAN_DATA_CLASS_1XEVDO_REVB 0x00200000 /* for future use */
|
||||
#define WWAN_DATA_CLASS_UMB 0x00400000
|
||||
#define WWAN_DATA_CLASS_CUSTOM 0x80000000
|
||||
|
||||
struct wwan_data_class_str {
|
||||
ULONG class;
|
||||
CHAR *str;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct _QCQMIMSG {
|
||||
QCQMI_HDR QMIHdr;
|
||||
union {
|
||||
QMICTL_MSG CTLMsg;
|
||||
QMUX_MSG MUXMsg;
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
QMUX_MSG QMUXMsgHdrResp;
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
};
|
||||
} __attribute__((packed)) QCQMIMSG, *PQCQMIMSG;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct __IPV4 {
|
||||
uint32_t Address;
|
||||
uint32_t Gateway;
|
||||
uint32_t SubnetMask;
|
||||
uint32_t DnsPrimary;
|
||||
uint32_t DnsSecondary;
|
||||
uint32_t Mtu;
|
||||
} IPV4_T;
|
||||
|
||||
typedef struct __IPV6 {
|
||||
UCHAR Address[16];
|
||||
UCHAR Gateway[16];
|
||||
UCHAR SubnetMask[16];
|
||||
UCHAR DnsPrimary[16];
|
||||
UCHAR DnsSecondary[16];
|
||||
UCHAR PrefixLengthIPAddr;
|
||||
UCHAR PrefixLengthGateway;
|
||||
ULONG Mtu;
|
||||
} IPV6_T;
|
||||
|
||||
#define IpFamilyV4 (0x04)
|
||||
#define IpFamilyV6 (0x06)
|
||||
|
||||
struct __PROFILE;
|
||||
struct qmi_device_ops {
|
||||
int (*init)(struct __PROFILE *profile);
|
||||
int (*deinit)(void);
|
||||
int (*send)(PQCQMIMSG pRequest);
|
||||
void *(*read)(void *pData);
|
||||
};
|
||||
extern int (*qmidev_send)(PQCQMIMSG pRequest);
|
||||
|
||||
#ifndef bool
|
||||
#define bool uint8_t
|
||||
#endif
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
typedef struct {
|
||||
unsigned int size;
|
||||
unsigned int rx_urb_size;
|
||||
unsigned int ep_type;
|
||||
unsigned int iface_id;
|
||||
unsigned int qmap_mode;
|
||||
unsigned int qmap_version;
|
||||
unsigned int dl_minimum_padding;
|
||||
char ifname[8][16];
|
||||
unsigned char mux_id[8];
|
||||
} RMNET_INFO;
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
|
||||
typedef struct __PROFILE {
|
||||
char *qmichannel;
|
||||
char *usbnet_adapter;
|
||||
char *qmapnet_adapter;
|
||||
const char *driver_name;
|
||||
int qmap_mode;
|
||||
int qmap_size;
|
||||
int qmap_version;
|
||||
const char *apn;
|
||||
const char *user;
|
||||
const char *password;
|
||||
const char *pincode;
|
||||
int auth;
|
||||
int pdp;
|
||||
int pdpindex;
|
||||
int pdpnum;
|
||||
int curIpFamily;
|
||||
int rawIP;
|
||||
int muxid;
|
||||
IPV4_T ipv4;
|
||||
IPV6_T ipv6;
|
||||
int ipv4_flag;
|
||||
int ipv6_flag;
|
||||
|
||||
//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001
|
||||
int ipv6_prigateway_flag;
|
||||
//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001
|
||||
|
||||
int dual_flag;
|
||||
int apntype;
|
||||
const struct qmi_device_ops *qmi_ops;
|
||||
bool loopback_state;
|
||||
int replication_factor;
|
||||
//2021-02-08 zhangkaibo@fibocom.com changed begin for mantis 0070613
|
||||
int interfacenum;
|
||||
//2021-02-08 zhangkaibo@fibocom.com changed end for mantis 0070613
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
RMNET_INFO rmnet_info;
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
} PROFILE_T;
|
||||
|
||||
typedef enum {
|
||||
SIM_ABSENT = 0,
|
||||
SIM_NOT_READY = 1,
|
||||
SIM_READY =
|
||||
2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
|
||||
SIM_PIN = 3,
|
||||
SIM_PUK = 4,
|
||||
SIM_NETWORK_PERSONALIZATION = 5,
|
||||
SIM_BAD = 6,
|
||||
} SIM_Status;
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
typedef enum {
|
||||
SIM_Card0 = 0,
|
||||
SIM_Card1 = 1
|
||||
} SIM_Select;
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
#define WDM_DEFAULT_BUFSIZE 256
|
||||
#define RIL_REQUEST_QUIT 0x1000
|
||||
#define RIL_INDICATE_DEVICE_CONNECTED 0x1002
|
||||
#define RIL_INDICATE_DEVICE_DISCONNECTED 0x1003
|
||||
#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 0x1004
|
||||
#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 0x1005
|
||||
|
||||
extern int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
unsigned msecs);
|
||||
extern int QmiThreadSendQMI(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse);
|
||||
extern int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse,
|
||||
unsigned msecs);
|
||||
extern void QmiThreadRecvQMI(PQCQMIMSG pResponse);
|
||||
extern int fibo_raw_ip_mode_check(const char *ifname);
|
||||
extern void udhcpc_start(PROFILE_T *profile);
|
||||
extern void udhcpc_stop(PROFILE_T *profile);
|
||||
extern void udhcpc_start_pcie(PROFILE_T *profile);
|
||||
extern void udhcpc_stop_pcie(PROFILE_T *profile);
|
||||
|
||||
extern void dump_qmi(void *dataBuffer, int dataLen);
|
||||
extern void qmidevice_send_event_to_main(int triger_event);
|
||||
extern int requestSetEthMode(PROFILE_T *profile);
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
//extern int requestGetSIMStatus(SIM_Status *pSIMStatus);
|
||||
extern int requestGetSIMStatus(SIM_Status *pSIMStatus , const int sim_select);
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
extern int requestEnterSimPin(const CHAR *pPinCode);
|
||||
extern int requestGetICCID(void);
|
||||
extern int requestGetIMSI(void);
|
||||
extern int requestRegistrationState(UCHAR *pPSAttachedState);
|
||||
extern int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily);
|
||||
extern int requestSetupDataCall(PROFILE_T *profile, int curIpFamily);
|
||||
extern int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily);
|
||||
extern int requestSetProfile(PROFILE_T *profile);
|
||||
extern int requestGetProfile(PROFILE_T *profile);
|
||||
extern int requestBaseBandVersion(const char **pp_reversion);
|
||||
extern int requestGetIPAddress(PROFILE_T *profile, int curIpFamily);
|
||||
extern int requestSetOperatingMode(UCHAR OperatingMode);
|
||||
int requestRegistrationState2(UCHAR *pPSAttachedState);
|
||||
|
||||
extern int fibo_qmap_mode_set(PROFILE_T *profile);
|
||||
extern int fibo_bridge_mode_detect(PROFILE_T *profile);
|
||||
extern int fibo_qmap_mode_detect(PROFILE_T *profile);
|
||||
extern const struct qmi_device_ops qmiwwan_qmidev_ops;
|
||||
|
||||
#define qmidev_is_gobinet(_qmichannel) \
|
||||
(strncmp(_qmichannel, "/dev/qcqmi", strlen("/dev/qcqmi")) == 0)
|
||||
#define qmidev_is_qmiwwan(_qmichannel) \
|
||||
(strncmp(_qmichannel, "/dev/cdc-wdm", strlen("/dev/cdc-wdm")) == 0)
|
||||
#define qmidev_is_pciemhi(_qmichannel) \
|
||||
(strncmp(_qmichannel, "/dev/mhi_", strlen("/dev/mhi_")) == 0)
|
||||
|
||||
#define driver_is_qmi(_drv_name) \
|
||||
(strncasecmp(_drv_name, "qmi_wwan", strlen("qmi_wwan")) == 0)
|
||||
#define driver_is_mbim(_drv_name) \
|
||||
(strncasecmp(_drv_name, "cdc_mbim", strlen("cdc_mbim")) == 0)
|
||||
|
||||
extern FILE *logfilefp;
|
||||
extern int debug_qmi;
|
||||
extern USHORT g_MobileCountryCode;
|
||||
extern USHORT g_MobileNetworkCode;
|
||||
extern int qmidevice_control_fd[2];
|
||||
extern int qmiclientId[QMUX_TYPE_WDS_ADMIN + 1];
|
||||
extern void dbg_time(const char *fmt, ...);
|
||||
extern USHORT le16_to_cpu(USHORT v16);
|
||||
extern UINT le32_to_cpu(UINT v32);
|
||||
extern USHORT cpu_to_le16(USHORT v16);
|
||||
extern UINT cpu_to_le32(UINT v32);
|
||||
#endif
|
||||
@ -1,426 +0,0 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
typedef unsigned short sa_family_t;
|
||||
#include <linux/un.h>
|
||||
|
||||
#include "QMIThread.h"
|
||||
|
||||
#ifdef CONFIG_QMIWWAN
|
||||
#define FIBO_QMI_PROXY "fibo_qmimsg_server"
|
||||
static int cdc_wdm_fd = -1;
|
||||
|
||||
static UCHAR GetQCTLTransactionId(void)
|
||||
{
|
||||
static int TransactionId = 0;
|
||||
if (++TransactionId > 0xFF)
|
||||
TransactionId = 1;
|
||||
return TransactionId;
|
||||
}
|
||||
|
||||
typedef USHORT (*CUSTOMQCTL)(PQMICTL_MSG pCTLMsg, void *arg);
|
||||
|
||||
static PQCQMIMSG ComposeQCTLMsg(USHORT QMICTLType,
|
||||
CUSTOMQCTL customQctlMsgFunction, void *arg)
|
||||
{
|
||||
UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE];
|
||||
PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf;
|
||||
int Length;
|
||||
|
||||
pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
|
||||
pRequest->QMIHdr.CtlFlags = 0x00;
|
||||
pRequest->QMIHdr.QMIType = QMUX_TYPE_CTL;
|
||||
pRequest->QMIHdr.ClientId = 0x00;
|
||||
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST;
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.TransactionId = GetQCTLTransactionId();
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.QMICTLType = cpu_to_le16(QMICTLType);
|
||||
if (customQctlMsgFunction)
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.Length =
|
||||
cpu_to_le16(customQctlMsgFunction(&pRequest->CTLMsg, arg) -
|
||||
sizeof(QCQMICTL_MSG_HDR));
|
||||
else
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(0x0000);
|
||||
|
||||
pRequest->QMIHdr.Length =
|
||||
cpu_to_le16(le16_to_cpu(pRequest->CTLMsg.QMICTLMsgHdr.Length) +
|
||||
sizeof(QCQMICTL_MSG_HDR) + sizeof(QCQMI_HDR) - 1);
|
||||
Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1;
|
||||
|
||||
pRequest = (PQCQMIMSG)malloc(Length);
|
||||
if (pRequest == NULL) {
|
||||
dbg_time("%s fail to malloc", __func__);
|
||||
} else {
|
||||
memcpy(pRequest, QMIBuf, Length);
|
||||
}
|
||||
|
||||
return pRequest;
|
||||
}
|
||||
|
||||
static USHORT CtlGetVersionReq(PQMICTL_MSG QCTLMsg, void *arg)
|
||||
{
|
||||
QCTLMsg->GetVersionReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
|
||||
QCTLMsg->GetVersionReq.TLVLength = cpu_to_le16(0x0001);
|
||||
QCTLMsg->GetVersionReq.QMUXTypes = QMUX_TYPE_ALL;
|
||||
return sizeof(QMICTL_GET_VERSION_REQ_MSG);
|
||||
}
|
||||
|
||||
static USHORT CtlGetClientIdReq(PQMICTL_MSG QCTLMsg, void *arg)
|
||||
{
|
||||
QCTLMsg->GetClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
|
||||
QCTLMsg->GetClientIdReq.TLVLength = cpu_to_le16(0x0001);
|
||||
QCTLMsg->GetClientIdReq.QMIType = ((UCHAR *)arg)[0];
|
||||
return sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG);
|
||||
}
|
||||
|
||||
static USHORT CtlReleaseClientIdReq(PQMICTL_MSG QCTLMsg, void *arg)
|
||||
{
|
||||
QCTLMsg->ReleaseClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
|
||||
QCTLMsg->ReleaseClientIdReq.TLVLength = cpu_to_le16(0x0002);
|
||||
QCTLMsg->ReleaseClientIdReq.QMIType = ((UCHAR *)arg)[0];
|
||||
QCTLMsg->ReleaseClientIdReq.ClientId = ((UCHAR *)arg)[1];
|
||||
return sizeof(QMICTL_RELEASE_CLIENT_ID_REQ_MSG);
|
||||
}
|
||||
|
||||
static int QmiWwanSendQMI(PQCQMIMSG pRequest)
|
||||
{
|
||||
struct pollfd pollfds[] = {{cdc_wdm_fd, POLLOUT, 0}};
|
||||
int ret;
|
||||
|
||||
if (cdc_wdm_fd == -1) {
|
||||
dbg_time("%s cdc_wdm_fd = -1", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pRequest->QMIHdr.QMIType == QMUX_TYPE_WDS_IPV6)
|
||||
pRequest->QMIHdr.QMIType = QMUX_TYPE_WDS;
|
||||
|
||||
do {
|
||||
ret = poll(pollfds, sizeof(pollfds) / sizeof(pollfds[0]), 5000);
|
||||
} while ((ret < 0) && (errno == EINTR));
|
||||
|
||||
if (pollfds[0].revents & POLLOUT) {
|
||||
ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1;
|
||||
ret = write(cdc_wdm_fd, pRequest, nwrites);
|
||||
if (ret == nwrites) {
|
||||
ret = 0;
|
||||
} else {
|
||||
dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno,
|
||||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
dbg_time("%s poll=%d, revents = 0x%x, errno: %d (%s)", __func__, ret,
|
||||
pollfds[0].revents, errno, strerror(errno));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int QmiWwanGetClientID(UCHAR QMIType)
|
||||
{
|
||||
PQCQMIMSG pResponse;
|
||||
|
||||
QmiThreadSendQMI(
|
||||
ComposeQCTLMsg(QMICTL_GET_CLIENT_ID_REQ, CtlGetClientIdReq, &QMIType),
|
||||
&pResponse);
|
||||
|
||||
if (pResponse) {
|
||||
USHORT QMUXResult = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp
|
||||
.QMUXResult); // QMI_RESULT_SUCCESS
|
||||
USHORT QMUXError = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp
|
||||
.QMUXError); // QMI_ERR_INVALID_ARG
|
||||
// UCHAR QMIType = pResponse->CTLMsg.GetClientIdRsp.QMIType;
|
||||
UCHAR ClientId = pResponse->CTLMsg.GetClientIdRsp.ClientId;
|
||||
|
||||
dbg_time("%s: QMIType = %d clientid %d", __func__, QMIType, ClientId);
|
||||
|
||||
if (!QMUXResult && !QMUXError &&
|
||||
(QMIType == pResponse->CTLMsg.GetClientIdRsp.QMIType)) {
|
||||
switch (QMIType) {
|
||||
case QMUX_TYPE_WDS:
|
||||
dbg_time("Get clientWDS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_DMS:
|
||||
dbg_time("Get clientDMS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_NAS:
|
||||
dbg_time("Get clientNAS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_QOS:
|
||||
dbg_time("Get clientQOS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_WMS:
|
||||
dbg_time("Get clientWMS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_PDS:
|
||||
dbg_time("Get clientPDS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_UIM:
|
||||
dbg_time("Get clientUIM = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_WDS_ADMIN:
|
||||
dbg_time("Get clientWDA = %d", ClientId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ClientId;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int QmiWwanReleaseClientID(QMI_SERVICE_TYPE QMIType, UCHAR ClientId)
|
||||
{
|
||||
UCHAR argv[] = {QMIType, ClientId};
|
||||
QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_RELEASE_CLIENT_ID_REQ,
|
||||
CtlReleaseClientIdReq, argv),
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int QmiWwanInit(PROFILE_T *profile)
|
||||
{
|
||||
unsigned i;
|
||||
int ret;
|
||||
PQCQMIMSG pResponse;
|
||||
|
||||
if (profile->qmap_mode == 0 || profile->qmap_mode == 1) {
|
||||
for (i = 0; i < 10; i++) {
|
||||
ret = QmiThreadSendQMITimeout(
|
||||
ComposeQCTLMsg(QMICTL_SYNC_REQ, NULL, NULL), NULL, 1 * 1000);
|
||||
if (!ret)
|
||||
break;
|
||||
sleep(1);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
QmiThreadSendQMI(
|
||||
ComposeQCTLMsg(QMICTL_GET_VERSION_REQ, CtlGetVersionReq, NULL),
|
||||
&pResponse);
|
||||
if (profile->qmap_mode) {
|
||||
if (pResponse) {
|
||||
if (pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 &&
|
||||
pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) {
|
||||
uint8_t NumElements = 0;
|
||||
|
||||
for (NumElements = 0;
|
||||
NumElements < pResponse->CTLMsg.GetVersionRsp.NumElements;
|
||||
NumElements++) {
|
||||
if (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements]
|
||||
.QMUXType == QMUX_TYPE_WDS_ADMIN)
|
||||
profile->qmap_version = (pResponse->CTLMsg.GetVersionRsp
|
||||
.TypeVersion[NumElements]
|
||||
.MinorVersion > 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pResponse)
|
||||
free(pResponse);
|
||||
if (profile->ipv4_flag)
|
||||
qmiclientId[QMUX_TYPE_WDS] = QmiWwanGetClientID(QMUX_TYPE_WDS);
|
||||
if (profile->ipv6_flag)
|
||||
qmiclientId[QMUX_TYPE_WDS_IPV6] = QmiWwanGetClientID(QMUX_TYPE_WDS);
|
||||
qmiclientId[QMUX_TYPE_DMS] = QmiWwanGetClientID(QMUX_TYPE_DMS);
|
||||
qmiclientId[QMUX_TYPE_NAS] = QmiWwanGetClientID(QMUX_TYPE_NAS);
|
||||
qmiclientId[QMUX_TYPE_UIM] = QmiWwanGetClientID(QMUX_TYPE_UIM);
|
||||
if (profile->qmap_mode == 0 || profile->qmap_mode == 1)
|
||||
qmiclientId[QMUX_TYPE_WDS_ADMIN] =
|
||||
QmiWwanGetClientID(QMUX_TYPE_WDS_ADMIN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int QmiWwanDeInit(void)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); i++) {
|
||||
if (qmiclientId[i] != 0) {
|
||||
QmiWwanReleaseClientID(i, qmiclientId[i]);
|
||||
qmiclientId[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qmi_proxy_open(const char *name)
|
||||
{
|
||||
int sockfd = -1;
|
||||
int reuse_addr = 1;
|
||||
struct sockaddr_un sockaddr;
|
||||
socklen_t alen;
|
||||
|
||||
/*Create server socket*/
|
||||
(sockfd = socket(AF_LOCAL, SOCK_STREAM, 0));
|
||||
if (sockfd < 0)
|
||||
return sockfd;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sun_family = AF_LOCAL;
|
||||
sockaddr.sun_path[0] = 0;
|
||||
memcpy(sockaddr.sun_path + 1, name, strlen(name));
|
||||
|
||||
alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1;
|
||||
if (connect(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) {
|
||||
close(sockfd);
|
||||
dbg_time("%s connect %s errno: %d (%s)\n", __func__, name, errno,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,
|
||||
sizeof(reuse_addr)));
|
||||
|
||||
dbg_time("connect to %s sockfd = %d\n", name, sockfd);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
static ssize_t qmi_proxy_read(int fd, void *buf, size_t size)
|
||||
{
|
||||
ssize_t nreads;
|
||||
PQCQMI_HDR pHdr = (PQCQMI_HDR)buf;
|
||||
|
||||
nreads = read(fd, pHdr, sizeof(QCQMI_HDR));
|
||||
if (nreads == sizeof(QCQMI_HDR)) {
|
||||
nreads += read(fd, pHdr + 1,
|
||||
le16_to_cpu(pHdr->Length) + 1 - sizeof(QCQMI_HDR));
|
||||
}
|
||||
|
||||
return nreads;
|
||||
}
|
||||
|
||||
static void *QmiWwanThread(void *pData)
|
||||
{
|
||||
PROFILE_T *profile = (PROFILE_T *)pData;
|
||||
const char *cdc_wdm = (const char *)profile->qmichannel;
|
||||
|
||||
if (profile->qmap_mode == 0 || profile->qmap_mode == 1)
|
||||
cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
else
|
||||
cdc_wdm_fd = qmi_proxy_open(FIBO_QMI_PROXY);
|
||||
|
||||
if (cdc_wdm_fd == -1) {
|
||||
dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, cdc_wdm,
|
||||
errno, strerror(errno));
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fcntl(cdc_wdm_fd, F_SETFL, fcntl(cdc_wdm_fd, F_GETFL) | O_NONBLOCK);
|
||||
fcntl(cdc_wdm_fd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
dbg_time("cdc_wdm_fd = %d", cdc_wdm_fd);
|
||||
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED);
|
||||
|
||||
while (1) {
|
||||
struct pollfd pollfds[] = {{qmidevice_control_fd[1], POLLIN, 0},
|
||||
{cdc_wdm_fd, POLLIN, 0}};
|
||||
int ne, ret, nevents = sizeof(pollfds) / sizeof(pollfds[0]);
|
||||
|
||||
do {
|
||||
ret = poll(pollfds, nevents, -1);
|
||||
} while ((ret < 0) && (errno == EINTR));
|
||||
|
||||
if (ret <= 0) {
|
||||
dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
for (ne = 0; ne < nevents; ne++) {
|
||||
int fd = pollfds[ne].fd;
|
||||
short revents = pollfds[ne].revents;
|
||||
|
||||
// dbg_time("{%d, %x, %x}", pollfds[ne].fd, pollfds[ne].events,
|
||||
// pollfds[ne].revents);
|
||||
|
||||
if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
||||
dbg_time("%s poll err/hup/inval", __func__);
|
||||
dbg_time("poll fd = %d, events = 0x%04x", fd, revents);
|
||||
if (fd == cdc_wdm_fd) {
|
||||
} else {
|
||||
}
|
||||
if (revents &
|
||||
(POLLHUP | POLLNVAL)) // EC20 bug, Can get POLLERR
|
||||
goto __QmiWwanThread_quit;
|
||||
}
|
||||
|
||||
if ((revents & POLLIN) == 0)
|
||||
continue;
|
||||
|
||||
if (fd == qmidevice_control_fd[1]) {
|
||||
int triger_event;
|
||||
if (read(fd, &triger_event, sizeof(triger_event)) ==
|
||||
sizeof(triger_event)) {
|
||||
// DBG("triger_event = 0x%x", triger_event);
|
||||
switch (triger_event) {
|
||||
case RIL_REQUEST_QUIT:
|
||||
goto __QmiWwanThread_quit;
|
||||
break;
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
QmiThreadRecvQMI(NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fd == cdc_wdm_fd) {
|
||||
ssize_t nreads;
|
||||
UCHAR QMIBuf[4096];
|
||||
PQCQMIMSG pResponse = (PQCQMIMSG)QMIBuf;
|
||||
|
||||
if (profile->qmap_mode == 0 || profile->qmap_mode == 1)
|
||||
nreads = read(fd, QMIBuf, sizeof(QMIBuf));
|
||||
else
|
||||
nreads = qmi_proxy_read(fd, QMIBuf, sizeof(QMIBuf));
|
||||
// dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads,
|
||||
// errno, strerror(errno));
|
||||
if (nreads <= 0) {
|
||||
dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads,
|
||||
errno, strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
if (nreads != (le16_to_cpu(pResponse->QMIHdr.Length) + 1)) {
|
||||
dbg_time("%s nreads=%d, pQCQMI->QMIHdr.Length = %d",
|
||||
__func__, (int)nreads,
|
||||
le16_to_cpu(pResponse->QMIHdr.Length));
|
||||
continue;
|
||||
}
|
||||
|
||||
QmiThreadRecvQMI(pResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__QmiWwanThread_quit:
|
||||
if (cdc_wdm_fd != -1) {
|
||||
close(cdc_wdm_fd);
|
||||
cdc_wdm_fd = -1;
|
||||
}
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
|
||||
QmiThreadRecvQMI(NULL); // main thread may pending on QmiThreadSendQMI()
|
||||
dbg_time("%s exit", __func__);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const struct qmi_device_ops qmiwwan_qmidev_ops = {
|
||||
.init = QmiWwanInit,
|
||||
.deinit = QmiWwanDeInit,
|
||||
.send = QmiWwanSendQMI,
|
||||
.read = QmiWwanThread,
|
||||
};
|
||||
@ -1,63 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Busybox udhcpc dispatcher script. Copyright (C) 2009 by Axel Beckert.
|
||||
#
|
||||
# Based on the busybox example scripts and the old udhcp source
|
||||
# package default.* scripts.
|
||||
|
||||
RESOLV_CONF="/etc/resolv.conf"
|
||||
|
||||
case $1 in
|
||||
bound|renew)
|
||||
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
|
||||
[ -n "$subnet" ] && NETMASK="netmask $subnet"
|
||||
|
||||
/sbin/ifconfig $interface $ip $BROADCAST $NETMASK
|
||||
|
||||
if [ -n "$router" ]; then
|
||||
echo "$0: Resetting default routes"
|
||||
while /sbin/route del default gw 0.0.0.0 dev $interface; do :; done
|
||||
|
||||
metric=0
|
||||
for i in $router; do
|
||||
/sbin/route add default gw $i dev $interface metric $metric
|
||||
metric=$(($metric + 1))
|
||||
done
|
||||
fi
|
||||
|
||||
# Update resolver configuration file
|
||||
R=""
|
||||
[ -n "$domain" ] && R="domain $domain
|
||||
"
|
||||
for i in $dns; do
|
||||
echo "$0: Adding DNS $i"
|
||||
R="${R}nameserver $i
|
||||
"
|
||||
done
|
||||
|
||||
if [ -x /sbin/resolvconf ]; then
|
||||
echo -n "$R" | resolvconf -a "${interface}.udhcpc"
|
||||
else
|
||||
echo -n "$R" > "$RESOLV_CONF"
|
||||
fi
|
||||
;;
|
||||
|
||||
deconfig)
|
||||
if [ -x /sbin/resolvconf ]; then
|
||||
resolvconf -d "${interface}.udhcpc"
|
||||
fi
|
||||
/sbin/ifconfig $interface 0.0.0.0
|
||||
;;
|
||||
|
||||
leasefail)
|
||||
echo "$0: Lease failed: $message"
|
||||
;;
|
||||
|
||||
nak)
|
||||
echo "$0: Received a NAK: $message"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "$0: Unknown udhcpc command: $1";
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,28 +0,0 @@
|
||||
= What is libmnl? =
|
||||
|
||||
libmnl is a minimalistic user-space library oriented to Netlink developers.
|
||||
There are a lot of common tasks in parsing, validating, constructing of
|
||||
both the Netlink header and TLVs that are repetitive and easy to get wrong.
|
||||
This library aims to provide simple helpers that allows you to re-use code
|
||||
and to avoid re-inventing the wheel. The main features of this library are:
|
||||
|
||||
* Small: the shared library requires around 30KB for an x86-based computer.
|
||||
* Simple: this library avoids complexity and elaborated abstractions that
|
||||
tend to hide Netlink details.
|
||||
* Easy to use: the library simplifies the work for Netlink-wise developers.
|
||||
It provides functions to make socket handling, message building, validating,
|
||||
parsing and sequence tracking, easier.
|
||||
* Easy to re-use: you can use the library to build your own abstraction layer
|
||||
on top of this library.
|
||||
* Decoupling: the interdependency of the main bricks that compose the library
|
||||
is reduced, i.e. the library provides many helpers, but the programmer is not
|
||||
forced to use them.
|
||||
|
||||
= Example files =
|
||||
|
||||
You can find several example files under examples/ that you can compile by
|
||||
invoking `make check'.
|
||||
|
||||
--
|
||||
08/sep/2010
|
||||
Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
@ -1,722 +0,0 @@
|
||||
/*
|
||||
* (C) 2008-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <limits.h> /* for INT_MAX */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
|
||||
/**
|
||||
* \defgroup attr Netlink attribute helpers
|
||||
*
|
||||
* Netlink Type-Length-Value (TLV) attribute:
|
||||
* \verbatim
|
||||
|<-- 2 bytes -->|<-- 2 bytes -->|<-- variable -->|
|
||||
-------------------------------------------------
|
||||
| length | type | value |
|
||||
-------------------------------------------------
|
||||
|<--------- header ------------>|<-- payload --->|
|
||||
\endverbatim
|
||||
* The payload of the Netlink message contains sequences of attributes that are
|
||||
* expressed in TLV format.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* mnl_attr_get_type - get type of netlink attribute
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the attribute type.
|
||||
*/
|
||||
uint16_t mnl_attr_get_type(const struct nlattr *attr)
|
||||
{
|
||||
return attr->nla_type & NLA_TYPE_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_len - get length of netlink attribute
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the attribute length that is the attribute header
|
||||
* plus the attribute payload.
|
||||
*/
|
||||
uint16_t mnl_attr_get_len(const struct nlattr *attr)
|
||||
{
|
||||
return attr->nla_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_payload_len - get the attribute payload-value length
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the attribute payload-value length.
|
||||
*/
|
||||
uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
|
||||
{
|
||||
return attr->nla_len - MNL_ATTR_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_payload - get pointer to the attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function return a pointer to the attribute payload.
|
||||
*/
|
||||
void *mnl_attr_get_payload(const struct nlattr *attr)
|
||||
{
|
||||
return (void *)attr + MNL_ATTR_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_ok - check if there is room for an attribute in a buffer
|
||||
* \param attr attribute that we want to check if there is room for
|
||||
* \param len remaining bytes in a buffer that contains the attribute
|
||||
*
|
||||
* This function is used to check that a buffer, which is supposed to contain
|
||||
* an attribute, has enough room for the attribute that it stores, i.e. this
|
||||
* function can be used to verify that an attribute is neither malformed nor
|
||||
* truncated.
|
||||
*
|
||||
* This function does not set errno in case of error since it is intended
|
||||
* for iterations. Thus, it returns true on success and false on error.
|
||||
*
|
||||
* The len parameter may be negative in the case of malformed messages during
|
||||
* attribute iteration, that is why we use a signed integer.
|
||||
*/
|
||||
bool mnl_attr_ok(const struct nlattr *attr, int len)
|
||||
{
|
||||
return len >= (int)sizeof(struct nlattr) &&
|
||||
attr->nla_len >= sizeof(struct nlattr) &&
|
||||
(int)attr->nla_len <= len;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_next - get the next attribute in the payload of a netlink message
|
||||
* \param attr pointer to the current attribute
|
||||
*
|
||||
* This function returns a pointer to the next attribute after the one passed
|
||||
* as parameter. You have to use mnl_attr_ok() to ensure that the next
|
||||
* attribute is valid.
|
||||
*/
|
||||
struct nlattr *mnl_attr_next(const struct nlattr *attr)
|
||||
{
|
||||
return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_type_valid - check if the attribute type is valid
|
||||
* \param attr pointer to attribute to be checked
|
||||
* \param max maximum attribute type
|
||||
*
|
||||
* This function allows to check if the attribute type is higher than the
|
||||
* maximum supported type. If the attribute type is invalid, this function
|
||||
* returns -1 and errno is explicitly set. On success, this function returns 1.
|
||||
*
|
||||
* Strict attribute checking in user-space is not a good idea since you may
|
||||
* run an old application with a newer kernel that supports new attributes.
|
||||
* This leads to backward compatibility breakages in user-space. Better check
|
||||
* if you support an attribute, if not, skip it.
|
||||
*/
|
||||
int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
|
||||
{
|
||||
if (mnl_attr_get_type(attr) > max) {
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __mnl_attr_validate(const struct nlattr *attr,
|
||||
enum mnl_attr_data_type type, size_t exp_len)
|
||||
{
|
||||
uint16_t attr_len = mnl_attr_get_payload_len(attr);
|
||||
const char *attr_data = mnl_attr_get_payload(attr);
|
||||
|
||||
if (attr_len < exp_len) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
switch(type) {
|
||||
case MNL_TYPE_FLAG:
|
||||
if (attr_len > 0) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MNL_TYPE_NUL_STRING:
|
||||
if (attr_len == 0) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
if (attr_data[attr_len-1] != '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MNL_TYPE_STRING:
|
||||
if (attr_len == 0) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MNL_TYPE_NESTED:
|
||||
/* empty nested attributes are OK. */
|
||||
if (attr_len == 0)
|
||||
break;
|
||||
/* if not empty, they must contain one header, eg. flag */
|
||||
if (attr_len < MNL_ATTR_HDRLEN) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* make gcc happy. */
|
||||
break;
|
||||
}
|
||||
if (exp_len && attr_len > exp_len) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
|
||||
[MNL_TYPE_U8] = sizeof(uint8_t),
|
||||
[MNL_TYPE_U16] = sizeof(uint16_t),
|
||||
[MNL_TYPE_U32] = sizeof(uint32_t),
|
||||
[MNL_TYPE_U64] = sizeof(uint64_t),
|
||||
[MNL_TYPE_MSECS] = sizeof(uint64_t),
|
||||
};
|
||||
|
||||
/**
|
||||
* mnl_attr_validate - validate netlink attribute (simplified version)
|
||||
* \param attr pointer to netlink attribute that we want to validate
|
||||
* \param type data type (see enum mnl_attr_data_type)
|
||||
*
|
||||
* The validation is based on the data type. Specifically, it checks that
|
||||
* integers (u8, u16, u32 and u64) have enough room for them. This function
|
||||
* returns -1 in case of error, and errno is explicitly set.
|
||||
*/
|
||||
int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
|
||||
{
|
||||
int exp_len;
|
||||
|
||||
if (type >= MNL_TYPE_MAX) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
exp_len = mnl_attr_data_type_len[type];
|
||||
return __mnl_attr_validate(attr, type, exp_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_validate2 - validate netlink attribute (extended version)
|
||||
* \param attr pointer to netlink attribute that we want to validate
|
||||
* \param type attribute type (see enum mnl_attr_data_type)
|
||||
* \param exp_len expected attribute data size
|
||||
*
|
||||
* This function allows to perform a more accurate validation for attributes
|
||||
* whose size is variable. If the size of the attribute is not what we expect,
|
||||
* this functions returns -1 and errno is explicitly set.
|
||||
*/
|
||||
int mnl_attr_validate2(const struct nlattr *attr,
|
||||
enum mnl_attr_data_type type,
|
||||
size_t exp_len)
|
||||
{
|
||||
if (type >= MNL_TYPE_MAX) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return __mnl_attr_validate(attr, type, exp_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_parse - parse attributes
|
||||
* \param nlh pointer to netlink message
|
||||
* \param offset offset to start parsing from (if payload is after any header)
|
||||
* \param cb callback function that is called for each attribute
|
||||
* \param data pointer to data that is passed to the callback function
|
||||
*
|
||||
* This function allows to iterate over the sequence of attributes that compose
|
||||
* the Netlink message. You can then put the attribute in an array as it
|
||||
* usually happens at this stage or you can use any other data structure (such
|
||||
* as lists or trees).
|
||||
*
|
||||
* This function propagates the return value of the callback, which can be
|
||||
* MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
|
||||
*/
|
||||
int mnl_attr_parse(const struct nlmsghdr *nlh,
|
||||
unsigned int offset, mnl_attr_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
int ret = MNL_CB_OK;
|
||||
const struct nlattr *attr;
|
||||
|
||||
mnl_attr_for_each(attr, nlh, offset)
|
||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_parse_nested - parse attributes inside a nest
|
||||
* \param nested pointer to netlink attribute that contains a nest
|
||||
* \param cb callback function that is called for each attribute in the nest
|
||||
* \param data pointer to data passed to the callback function
|
||||
*
|
||||
* This function allows to iterate over the sequence of attributes that compose
|
||||
* the Netlink message. You can then put the attribute in an array as it
|
||||
* usually happens at this stage or you can use any other data structure (such
|
||||
* as lists or trees).
|
||||
*
|
||||
* This function propagates the return value of the callback, which can be
|
||||
* MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
|
||||
*/
|
||||
int mnl_attr_parse_nested(const struct nlattr *nested,
|
||||
mnl_attr_cb_t cb, void *data)
|
||||
{
|
||||
int ret = MNL_CB_OK;
|
||||
const struct nlattr *attr;
|
||||
|
||||
mnl_attr_for_each_nested(attr, nested)
|
||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_parse_payload - parse attributes in payload of Netlink message
|
||||
* \param payload pointer to payload of the Netlink message
|
||||
* \param payload_len payload length that contains the attributes
|
||||
* \param cb callback function that is called for each attribute
|
||||
* \param data pointer to data that is passed to the callback function
|
||||
*
|
||||
* This function takes a pointer to the area that contains the attributes,
|
||||
* commonly known as the payload of the Netlink message. Thus, you have to
|
||||
* pass a pointer to the Netlink message payload, instead of the entire
|
||||
* message.
|
||||
*
|
||||
* This function allows you to iterate over the sequence of attributes that are
|
||||
* located at some payload offset. You can then put the attributes in one array
|
||||
* as usual, or you can use any other data structure (such as lists or trees).
|
||||
*
|
||||
* This function propagates the return value of the callback, which can be
|
||||
* MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
|
||||
*/
|
||||
int mnl_attr_parse_payload(const void *payload,
|
||||
size_t payload_len,
|
||||
mnl_attr_cb_t cb, void *data)
|
||||
{
|
||||
int ret = MNL_CB_OK;
|
||||
const struct nlattr *attr;
|
||||
|
||||
mnl_attr_for_each_payload(payload, payload_len)
|
||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_u8 - returns 8-bit unsigned integer attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 8-bit value of the attribute payload.
|
||||
*/
|
||||
uint8_t mnl_attr_get_u8(const struct nlattr *attr)
|
||||
{
|
||||
return *((uint8_t *)mnl_attr_get_payload(attr));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_u16 - returns 16-bit unsigned integer attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 16-bit value of the attribute payload.
|
||||
*/
|
||||
uint16_t mnl_attr_get_u16(const struct nlattr *attr)
|
||||
{
|
||||
return *((uint16_t *)mnl_attr_get_payload(attr));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_u32 - returns 32-bit unsigned integer attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 32-bit value of the attribute payload.
|
||||
*/
|
||||
uint32_t mnl_attr_get_u32(const struct nlattr *attr)
|
||||
{
|
||||
return *((uint32_t *)mnl_attr_get_payload(attr));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_u64 - returns 64-bit unsigned integer attribute.
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 64-bit value of the attribute payload. This
|
||||
* function is align-safe, since accessing 64-bit Netlink attributes is a
|
||||
* common source of alignment issues.
|
||||
*/
|
||||
uint64_t mnl_attr_get_u64(const struct nlattr *attr)
|
||||
{
|
||||
uint64_t tmp;
|
||||
memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_str - returns pointer to string attribute.
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the payload of string attribute value.
|
||||
*/
|
||||
const char *mnl_attr_get_str(const struct nlattr *attr)
|
||||
{
|
||||
return mnl_attr_get_payload(attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put - add an attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type that you want to add
|
||||
* \param len netlink attribute payload length
|
||||
* \param data pointer to the data that will be stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type,
|
||||
size_t len, const void *data)
|
||||
{
|
||||
struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
|
||||
uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
|
||||
int pad;
|
||||
|
||||
attr->nla_type = type;
|
||||
attr->nla_len = payload_len;
|
||||
memcpy(mnl_attr_get_payload(attr), data, len);
|
||||
pad = MNL_ALIGN(len) - len;
|
||||
if (pad > 0)
|
||||
memset(mnl_attr_get_payload(attr) + len, 0, pad);
|
||||
|
||||
nlh->nlmsg_len += MNL_ALIGN(payload_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u8 - add 8-bit unsigned integer attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data 8-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type,
|
||||
uint8_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u16 - add 16-bit unsigned integer attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data 16-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type,
|
||||
uint16_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u32 - add 32-bit unsigned integer attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data 32-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type,
|
||||
uint32_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u64 - add 64-bit unsigned integer attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data 64-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type,
|
||||
uint64_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_str - add string attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data pointer to string data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type,
|
||||
const char *data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, strlen(data), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_strz - add string attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data pointer to string data that is stored by the new attribute
|
||||
*
|
||||
* This function is similar to mnl_attr_put_str, but it includes the
|
||||
* NUL/zero ('\0') terminator at the end of the string.
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type,
|
||||
const char *data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, strlen(data)+1, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_nest_start - start an attribute nest
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
*
|
||||
* This function adds the attribute header that identifies the beginning of
|
||||
* an attribute nest. This function always returns a valid pointer to the
|
||||
* beginning of the nest.
|
||||
*/
|
||||
struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh,
|
||||
uint16_t type)
|
||||
{
|
||||
struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
|
||||
|
||||
/* set start->nla_len in mnl_attr_nest_end() */
|
||||
start->nla_type = NLA_F_NESTED | type;
|
||||
nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_check - add an attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type that you want to add
|
||||
* \param len netlink attribute payload length
|
||||
* \param data pointer to the data that will be stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
*/
|
||||
bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, size_t len,
|
||||
const void *data)
|
||||
{
|
||||
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
|
||||
return false;
|
||||
mnl_attr_put(nlh, type, len, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u8_check - add 8-bit unsigned int attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data 8-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
*/
|
||||
bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint8_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u16_check - add 16-bit unsigned int attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data 16-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint16_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u32_check - add 32-bit unsigned int attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data 32-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint32_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u64_check - add 64-bit unsigned int attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data 64-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint64_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_str_check - add string attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data pointer to string data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, const char *data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_strz_check - add string attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data pointer to string data that is stored by the new attribute
|
||||
*
|
||||
* This function is similar to mnl_attr_put_str, but it includes the
|
||||
* NUL/zero ('\0') terminator at the end of the string.
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
*/
|
||||
bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, const char *data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_nest_start_check - start an attribute nest
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
*
|
||||
* This function adds the attribute header that identifies the beginning of
|
||||
* an attribute nest. If the nested attribute cannot be added then NULL,
|
||||
* otherwise valid pointer to the beginning of the nest is returned.
|
||||
*/
|
||||
struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh,
|
||||
size_t buflen,
|
||||
uint16_t type)
|
||||
{
|
||||
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
|
||||
return NULL;
|
||||
return mnl_attr_nest_start(nlh, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_nest_end - end an attribute nest
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param start pointer to the attribute nest returned by mnl_attr_nest_start()
|
||||
*
|
||||
* This function updates the attribute header that identifies the nest.
|
||||
*/
|
||||
void mnl_attr_nest_end(struct nlmsghdr *nlh,
|
||||
struct nlattr *start)
|
||||
{
|
||||
start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_nest_cancel - cancel an attribute nest
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param start pointer to the attribute nest returned by mnl_attr_nest_start()
|
||||
*
|
||||
* This function updates the attribute header that identifies the nest.
|
||||
*/
|
||||
void mnl_attr_nest_cancel(struct nlmsghdr *nlh,
|
||||
struct nlattr *start)
|
||||
{
|
||||
nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
|
||||
static int mnl_cb_noop(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int mnl_cb_error(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
||||
|
||||
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
|
||||
errno = EBADMSG;
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
/* Netlink subsystems returns the errno value with different signess */
|
||||
if (err->error < 0)
|
||||
errno = -err->error;
|
||||
else
|
||||
errno = err->error;
|
||||
|
||||
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
static int mnl_cb_stop(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
return MNL_CB_STOP;
|
||||
}
|
||||
|
||||
static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
|
||||
[NLMSG_NOOP] = mnl_cb_noop,
|
||||
[NLMSG_ERROR] = mnl_cb_error,
|
||||
[NLMSG_DONE] = mnl_cb_stop,
|
||||
[NLMSG_OVERRUN] = mnl_cb_noop,
|
||||
};
|
||||
|
||||
static inline int __mnl_cb_run(const void *buf, size_t numbytes,
|
||||
unsigned int seq, unsigned int portid,
|
||||
mnl_cb_t cb_data, void *data,
|
||||
const mnl_cb_t *cb_ctl_array,
|
||||
unsigned int cb_ctl_array_len)
|
||||
{
|
||||
int ret = MNL_CB_OK, len = numbytes;
|
||||
const struct nlmsghdr *nlh = buf;
|
||||
|
||||
while (mnl_nlmsg_ok(nlh, len)) {
|
||||
/* check message source */
|
||||
if (!mnl_nlmsg_portid_ok(nlh, portid)) {
|
||||
errno = ESRCH;
|
||||
return -1;
|
||||
}
|
||||
/* perform sequence tracking */
|
||||
if (!mnl_nlmsg_seq_ok(nlh, seq)) {
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* dump was interrupted */
|
||||
if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* netlink data message handling */
|
||||
if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
|
||||
if (cb_data){
|
||||
ret = cb_data(nlh, data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
goto out;
|
||||
}
|
||||
} else if (nlh->nlmsg_type < cb_ctl_array_len) {
|
||||
if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
|
||||
ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
goto out;
|
||||
}
|
||||
} else if (default_cb_array[nlh->nlmsg_type]) {
|
||||
ret = default_cb_array[nlh->nlmsg_type](nlh, data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
goto out;
|
||||
}
|
||||
nlh = mnl_nlmsg_next(nlh, &len);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \defgroup callback Callback helpers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* mnl_cb_run2 - callback runqueue for netlink messages
|
||||
* \param buf buffer that contains the netlink messages
|
||||
* \param numbytes number of bytes stored in the buffer
|
||||
* \param seq sequence number that we expect to receive
|
||||
* \param portid Netlink PortID that we expect to receive
|
||||
* \param cb_data callback handler for data messages
|
||||
* \param data pointer to data that will be passed to the data callback handler
|
||||
* \param cb_ctl_array array of custom callback handlers from control messages
|
||||
* \param cb_ctl_array_len array length of custom control callback handlers
|
||||
*
|
||||
* You can set the cb_ctl_array to NULL if you want to use the default control
|
||||
* callback handlers, in that case, the parameter cb_ctl_array_len is not
|
||||
* checked.
|
||||
*
|
||||
* Your callback may return three possible values:
|
||||
* - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
|
||||
* - MNL_CB_STOP (=0): stop callback runqueue.
|
||||
* - MNL_CB_OK (>=1): no problem has occurred.
|
||||
*
|
||||
* This function propagates the callback return value. On error, it returns
|
||||
* -1 and errno is explicitly set. If the portID is not the expected, errno
|
||||
* is set to ESRCH. If the sequence number is not the expected, errno is set
|
||||
* to EPROTO. If the dump was interrupted, errno is set to EINTR and you should
|
||||
* request a new fresh dump again.
|
||||
*/
|
||||
int mnl_cb_run2(const void *buf, size_t numbytes,
|
||||
unsigned int seq, unsigned int portid,
|
||||
mnl_cb_t cb_data, void *data,
|
||||
const mnl_cb_t *cb_ctl_array,
|
||||
unsigned int cb_ctl_array_len)
|
||||
{
|
||||
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
|
||||
cb_ctl_array, cb_ctl_array_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_cb_run - callback runqueue for netlink messages (simplified version)
|
||||
* \param buf buffer that contains the netlink messages
|
||||
* \param numbytes number of bytes stored in the buffer
|
||||
* \param seq sequence number that we expect to receive
|
||||
* \param portid Netlink PortID that we expect to receive
|
||||
* \param cb_data callback handler for data messages
|
||||
* \param data pointer to data that will be passed to the data callback handler
|
||||
*
|
||||
* This function is like mnl_cb_run2() but it does not allow you to set
|
||||
* the control callback handlers.
|
||||
*
|
||||
* Your callback may return three possible values:
|
||||
* - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
|
||||
* - MNL_CB_STOP (=0): stop callback runqueue.
|
||||
* - MNL_CB_OK (>=1): no problems has occurred.
|
||||
*
|
||||
* This function propagates the callback return value.
|
||||
*/
|
||||
int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
|
||||
unsigned int portid, mnl_cb_t cb_data, void *data)
|
||||
{
|
||||
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@ -1,5 +0,0 @@
|
||||
#ifndef __DHCP_H__
|
||||
#define __DHCP_H__
|
||||
|
||||
int do_dhcp(char *iname);
|
||||
#endif //__DHCP_H__
|
||||
@ -1,515 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <net/if.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "../ifutils.h"
|
||||
#include "dhcpmsg.h"
|
||||
#include "packet.h"
|
||||
|
||||
#define VERBOSE 2
|
||||
|
||||
static int verbose = 1;
|
||||
static char errmsg[2048];
|
||||
|
||||
typedef unsigned long long msecs_t;
|
||||
#if VERBOSE
|
||||
void dump_dhcp_msg();
|
||||
#endif
|
||||
|
||||
msecs_t get_msecs(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
|
||||
return 0;
|
||||
} else {
|
||||
return (((msecs_t) ts.tv_sec) * ((msecs_t) 1000)) +
|
||||
(((msecs_t) ts.tv_nsec) / ((msecs_t) 1000000));
|
||||
}
|
||||
}
|
||||
|
||||
void printerr(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(errmsg, sizeof(errmsg), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
printf("%s\n", errmsg);
|
||||
}
|
||||
|
||||
const char *dhcp_lasterror()
|
||||
{
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
int fatal(const char *reason)
|
||||
{
|
||||
printerr("%s: %s\n", reason, strerror(errno));
|
||||
return -1;
|
||||
// exit(1);
|
||||
}
|
||||
|
||||
typedef struct dhcp_info dhcp_info;
|
||||
|
||||
struct dhcp_info {
|
||||
uint32_t type;
|
||||
|
||||
uint32_t ipaddr;
|
||||
uint32_t gateway;
|
||||
uint32_t prefixLength;
|
||||
|
||||
uint32_t dns1;
|
||||
uint32_t dns2;
|
||||
|
||||
uint32_t serveraddr;
|
||||
uint32_t lease;
|
||||
};
|
||||
|
||||
dhcp_info last_good_info;
|
||||
|
||||
void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *prefixLength,
|
||||
uint32_t *dns1, uint32_t *dns2, uint32_t *server,
|
||||
uint32_t *lease)
|
||||
{
|
||||
*ipaddr = last_good_info.ipaddr;
|
||||
*gateway = last_good_info.gateway;
|
||||
*prefixLength = last_good_info.prefixLength;
|
||||
*dns1 = last_good_info.dns1;
|
||||
*dns2 = last_good_info.dns2;
|
||||
*server = last_good_info.serveraddr;
|
||||
*lease = last_good_info.lease;
|
||||
}
|
||||
|
||||
static int dhcp_configure(const char *ifname, dhcp_info *info)
|
||||
{
|
||||
last_good_info = *info;
|
||||
return if_set_network_v4(ifname, info->ipaddr, info->prefixLength, info->gateway,
|
||||
info->dns1, info->dns2);
|
||||
}
|
||||
|
||||
static const char *dhcp_type_to_name(uint32_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case DHCPDISCOVER: return "discover";
|
||||
case DHCPOFFER: return "offer";
|
||||
case DHCPREQUEST: return "request";
|
||||
case DHCPDECLINE: return "decline";
|
||||
case DHCPACK: return "ack";
|
||||
case DHCPNAK: return "nak";
|
||||
case DHCPRELEASE: return "release";
|
||||
case DHCPINFORM: return "inform";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
||||
void dump_dhcp_info(dhcp_info *info)
|
||||
{
|
||||
char addr[20], gway[20];
|
||||
printf("--- dhcp %s (%d) ---\n",
|
||||
dhcp_type_to_name(info->type), info->type);
|
||||
strcpy(addr, ipaddr_to_string_v4(info->ipaddr));
|
||||
strcpy(gway, ipaddr_to_string_v4(info->gateway));
|
||||
printf("ip %s gw %s prefixLength %d\n", addr, gway, info->prefixLength);
|
||||
if (info->dns1) printf("dns1: %s\n", ipaddr_to_string_v4(info->dns1));
|
||||
if (info->dns2) printf("dns2: %s\n", ipaddr_to_string_v4(info->dns2));
|
||||
printf("server %s, lease %d seconds\n",
|
||||
ipaddr_to_string_v4(info->serveraddr), info->lease);
|
||||
}
|
||||
|
||||
|
||||
int decode_dhcp_msg(dhcp_msg *msg, int len, dhcp_info *info)
|
||||
{
|
||||
uint8_t *x;
|
||||
unsigned int opt;
|
||||
int optlen;
|
||||
|
||||
memset(info, 0, sizeof(dhcp_info));
|
||||
if (len < (DHCP_MSG_FIXED_SIZE + 4)) return -1;
|
||||
|
||||
len -= (DHCP_MSG_FIXED_SIZE + 4);
|
||||
|
||||
if (msg->options[0] != OPT_COOKIE1) return -1;
|
||||
if (msg->options[1] != OPT_COOKIE2) return -1;
|
||||
if (msg->options[2] != OPT_COOKIE3) return -1;
|
||||
if (msg->options[3] != OPT_COOKIE4) return -1;
|
||||
|
||||
x = msg->options + 4;
|
||||
|
||||
while (len > 2) {
|
||||
opt = *x++;
|
||||
if (opt == OPT_PAD) {
|
||||
len--;
|
||||
continue;
|
||||
}
|
||||
if (opt == OPT_END) {
|
||||
break;
|
||||
}
|
||||
optlen = *x++;
|
||||
len -= 2;
|
||||
if (optlen > len) {
|
||||
break;
|
||||
}
|
||||
switch(opt) {
|
||||
case OPT_SUBNET_MASK:
|
||||
if (optlen >= 4) {
|
||||
in_addr_t mask;
|
||||
memcpy(&mask, x, 4);
|
||||
info->prefixLength = mask_to_prefix_v4(mask);
|
||||
}
|
||||
break;
|
||||
case OPT_GATEWAY:
|
||||
if (optlen >= 4) memcpy(&info->gateway, x, 4);
|
||||
break;
|
||||
case OPT_DNS:
|
||||
if (optlen >= 4) memcpy(&info->dns1, x + 0, 4);
|
||||
if (optlen >= 8) memcpy(&info->dns2, x + 4, 4);
|
||||
break;
|
||||
case OPT_LEASE_TIME:
|
||||
if (optlen >= 4) {
|
||||
memcpy(&info->lease, x, 4);
|
||||
info->lease = ntohl(info->lease);
|
||||
}
|
||||
break;
|
||||
case OPT_SERVER_ID:
|
||||
if (optlen >= 4) memcpy(&info->serveraddr, x, 4);
|
||||
break;
|
||||
case OPT_MESSAGE_TYPE:
|
||||
info->type = *x;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
x += optlen;
|
||||
len -= optlen;
|
||||
}
|
||||
|
||||
info->ipaddr = msg->yiaddr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if VERBOSE
|
||||
|
||||
static void hex2str(char *buf, size_t buf_size, const unsigned char *array, int len)
|
||||
{
|
||||
int i;
|
||||
char *cp = buf;
|
||||
char *buf_end = buf + buf_size;
|
||||
for (i = 0; i < len; i++) {
|
||||
cp += snprintf(cp, buf_end - cp, " %02x ", array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void dump_dhcp_msg(dhcp_msg *msg, int len)
|
||||
{
|
||||
unsigned char *x;
|
||||
unsigned int n,c;
|
||||
int optsz;
|
||||
const char *name;
|
||||
char buf[2048];
|
||||
|
||||
if (len < DHCP_MSG_FIXED_SIZE) {
|
||||
printf("Invalid length %d, should be %d", len, DHCP_MSG_FIXED_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
len -= DHCP_MSG_FIXED_SIZE;
|
||||
|
||||
if (msg->op == OP_BOOTREQUEST)
|
||||
name = "BOOTREQUEST";
|
||||
else if (msg->op == OP_BOOTREPLY)
|
||||
name = "BOOTREPLY";
|
||||
else
|
||||
name = "????";
|
||||
|
||||
c = msg->hlen > 16 ? 16 : msg->hlen;
|
||||
hex2str(buf, sizeof(buf), msg->chaddr, c);
|
||||
|
||||
for (n = 0; n < 64; n++) {
|
||||
unsigned char x = msg->sname[n];
|
||||
if ((x < ' ') || (x > 127)) {
|
||||
if (x == 0) break;
|
||||
msg->sname[n] = '.';
|
||||
}
|
||||
}
|
||||
msg->sname[63] = 0;
|
||||
|
||||
for (n = 0; n < 128; n++) {
|
||||
unsigned char x = msg->file[n];
|
||||
if ((x < ' ') || (x > 127)) {
|
||||
if (x == 0) break;
|
||||
msg->file[n] = '.';
|
||||
}
|
||||
}
|
||||
msg->file[127] = 0;
|
||||
|
||||
if (len < 4) return;
|
||||
len -= 4;
|
||||
x = msg->options + 4;
|
||||
|
||||
while (len > 2) {
|
||||
if (*x == 0) {
|
||||
x++;
|
||||
len--;
|
||||
continue;
|
||||
}
|
||||
if (*x == OPT_END) {
|
||||
break;
|
||||
}
|
||||
len -= 2;
|
||||
optsz = x[1];
|
||||
if (optsz > len) break;
|
||||
if (x[0] == OPT_DOMAIN_NAME || x[0] == OPT_MESSAGE) {
|
||||
if ((unsigned int)optsz < sizeof(buf) - 1) {
|
||||
n = optsz;
|
||||
} else {
|
||||
n = sizeof(buf) - 1;
|
||||
}
|
||||
memcpy(buf, &x[2], n);
|
||||
buf[n] = '\0';
|
||||
} else {
|
||||
hex2str(buf, sizeof(buf), &x[2], optsz);
|
||||
}
|
||||
if (x[0] == OPT_MESSAGE_TYPE)
|
||||
name = dhcp_type_to_name(x[2]);
|
||||
else
|
||||
name = NULL;
|
||||
len -= optsz;
|
||||
x = x + optsz + 2;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int send_message(int sock, int if_index, dhcp_msg *msg, int size)
|
||||
{
|
||||
#if VERBOSE > 1
|
||||
dump_dhcp_msg(msg, size);
|
||||
#endif
|
||||
return send_packet(sock, if_index, msg, size, INADDR_ANY, INADDR_BROADCAST,
|
||||
PORT_BOOTP_CLIENT, PORT_BOOTP_SERVER);
|
||||
}
|
||||
|
||||
static int is_valid_reply(dhcp_msg *msg, dhcp_msg *reply, int sz)
|
||||
{
|
||||
if (sz < DHCP_MSG_FIXED_SIZE) {
|
||||
if (verbose) printf("Wrong size %d != %d\n", sz, DHCP_MSG_FIXED_SIZE);
|
||||
return 0;
|
||||
}
|
||||
if (reply->op != OP_BOOTREPLY) {
|
||||
if (verbose) printf("Wrong Op %d != %d\n", reply->op, OP_BOOTREPLY);
|
||||
return 0;
|
||||
}
|
||||
if (reply->xid != msg->xid) {
|
||||
if (verbose) printf("Wrong Xid 0x%x != 0x%x\n", ntohl(reply->xid),
|
||||
ntohl(msg->xid));
|
||||
return 0;
|
||||
}
|
||||
if (reply->htype != msg->htype) {
|
||||
if (verbose) printf("Wrong Htype %d != %d\n", reply->htype, msg->htype);
|
||||
return 0;
|
||||
}
|
||||
if (reply->hlen != msg->hlen) {
|
||||
if (verbose) printf("Wrong Hlen %d != %d\n", reply->hlen, msg->hlen);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(msg->chaddr, reply->chaddr, msg->hlen)) {
|
||||
if (verbose) printf("Wrong chaddr %x != %x\n", *(reply->chaddr),*(msg->chaddr));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define STATE_SELECTING 1
|
||||
#define STATE_REQUESTING 2
|
||||
|
||||
#define TIMEOUT_INITIAL 4000
|
||||
#define TIMEOUT_MAX 32000
|
||||
|
||||
int dhcp_init_ifc(const char *ifname)
|
||||
{
|
||||
dhcp_msg discover_msg;
|
||||
dhcp_msg request_msg;
|
||||
dhcp_msg reply;
|
||||
dhcp_msg *msg;
|
||||
dhcp_info info;
|
||||
int s, r, size;
|
||||
int valid_reply;
|
||||
uint32_t xid;
|
||||
unsigned char hwaddr[6];
|
||||
struct pollfd pfd;
|
||||
unsigned int state;
|
||||
unsigned int timeout;
|
||||
int if_index;
|
||||
|
||||
xid = (uint32_t) get_msecs();
|
||||
|
||||
if (if_get_hwaddr(ifname, hwaddr)) {
|
||||
return fatal("cannot obtain interface address");
|
||||
}
|
||||
if ((if_index = if_nametoindex(ifname)) == 0) {
|
||||
return fatal("cannot obtain interface index");
|
||||
}
|
||||
|
||||
s = open_raw_socket(ifname, hwaddr, if_index);
|
||||
|
||||
timeout = TIMEOUT_INITIAL;
|
||||
state = STATE_SELECTING;
|
||||
info.type = 0;
|
||||
goto transmit;
|
||||
|
||||
for (;;) {
|
||||
pfd.fd = s;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
r = poll(&pfd, 1, timeout);
|
||||
|
||||
if (r == 0) {
|
||||
#if VERBOSE
|
||||
printerr("TIMEOUT\n");
|
||||
#endif
|
||||
if (timeout >= TIMEOUT_MAX) {
|
||||
printerr("timed out\n");
|
||||
if ( info.type == DHCPOFFER ) {
|
||||
printerr("no acknowledgement from DHCP server\nconfiguring %s with offered parameters\n", ifname);
|
||||
return dhcp_configure(ifname, &info);
|
||||
}
|
||||
errno = ETIME;
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
timeout = timeout * 2;
|
||||
|
||||
transmit:
|
||||
size = 0;
|
||||
msg = NULL;
|
||||
switch(state) {
|
||||
case STATE_SELECTING:
|
||||
msg = &discover_msg;
|
||||
size = init_dhcp_discover_msg(msg, hwaddr, xid);
|
||||
break;
|
||||
case STATE_REQUESTING:
|
||||
msg = &request_msg;
|
||||
size = init_dhcp_request_msg(msg, hwaddr, xid, info.ipaddr, info.serveraddr);
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
}
|
||||
if (size != 0) {
|
||||
r = send_message(s, if_index, msg, size);
|
||||
if (r < 0) {
|
||||
printerr("error sending dhcp msg: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
if ((errno == EAGAIN) || (errno == EINTR)) {
|
||||
continue;
|
||||
}
|
||||
return fatal("poll failed");
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
r = receive_packet(s, &reply);
|
||||
if (r < 0) {
|
||||
if (errno != 0) {
|
||||
printf("receive_packet failed (%d): %s", r, strerror(errno));
|
||||
if (errno == ENETDOWN || errno == ENXIO) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
#if VERBOSE > 1
|
||||
dump_dhcp_msg(&reply, r);
|
||||
#endif
|
||||
decode_dhcp_msg(&reply, r, &info);
|
||||
|
||||
if (state == STATE_SELECTING) {
|
||||
valid_reply = is_valid_reply(&discover_msg, &reply, r);
|
||||
} else {
|
||||
valid_reply = is_valid_reply(&request_msg, &reply, r);
|
||||
}
|
||||
if (!valid_reply) {
|
||||
printerr("invalid reply\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose) dump_dhcp_info(&info);
|
||||
|
||||
switch(state) {
|
||||
case STATE_SELECTING:
|
||||
if (info.type == DHCPOFFER) {
|
||||
state = STATE_REQUESTING;
|
||||
timeout = TIMEOUT_INITIAL;
|
||||
xid++;
|
||||
goto transmit;
|
||||
}
|
||||
break;
|
||||
case STATE_REQUESTING:
|
||||
if (info.type == DHCPACK) {
|
||||
printerr("configuring %s\n", ifname);
|
||||
close(s);
|
||||
return dhcp_configure(ifname, &info);
|
||||
} else if (info.type == DHCPNAK) {
|
||||
printerr("configuration request denied\n");
|
||||
close(s);
|
||||
return -1;
|
||||
} else {
|
||||
printerr("ignoring %s message in state %d\n",
|
||||
dhcp_type_to_name(info.type), state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_dhcp(char *iname)
|
||||
{
|
||||
if (if_set_addr_v4(iname, 0, 32)) {
|
||||
printerr("failed to set ip addr for %s to 0.0.0.0: %s\n", iname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (if_link_up(iname)) {
|
||||
printerr("failed to bring up interface %s: %s\n", iname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dhcp_init_ifc(iname);
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "dhcpmsg.h"
|
||||
|
||||
static void *init_dhcp_msg(dhcp_msg *msg, int type, void *hwaddr, uint32_t xid)
|
||||
{
|
||||
uint8_t *x;
|
||||
|
||||
memset(msg, 0, sizeof(dhcp_msg));
|
||||
|
||||
msg->op = OP_BOOTREQUEST;
|
||||
msg->htype = HTYPE_ETHER;
|
||||
msg->hlen = 6;
|
||||
msg->hops = 0;
|
||||
|
||||
msg->flags = htons(FLAGS_BROADCAST);
|
||||
|
||||
msg->xid = xid;
|
||||
|
||||
memcpy(msg->chaddr, hwaddr, 6);
|
||||
|
||||
x = msg->options;
|
||||
|
||||
*x++ = OPT_COOKIE1;
|
||||
*x++ = OPT_COOKIE2;
|
||||
*x++ = OPT_COOKIE3;
|
||||
*x++ = OPT_COOKIE4;
|
||||
|
||||
*x++ = OPT_MESSAGE_TYPE;
|
||||
*x++ = 1;
|
||||
*x++ = type;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
int init_dhcp_discover_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid)
|
||||
{
|
||||
uint8_t *x;
|
||||
|
||||
x = init_dhcp_msg(msg, DHCPDISCOVER, hwaddr, xid);
|
||||
|
||||
*x++ = OPT_PARAMETER_LIST;
|
||||
*x++ = 4;
|
||||
*x++ = OPT_SUBNET_MASK;
|
||||
*x++ = OPT_GATEWAY;
|
||||
*x++ = OPT_DNS;
|
||||
*x++ = OPT_BROADCAST_ADDR;
|
||||
|
||||
*x++ = OPT_END;
|
||||
|
||||
return DHCP_MSG_FIXED_SIZE + (x - msg->options);
|
||||
}
|
||||
|
||||
int init_dhcp_request_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid,
|
||||
uint32_t ipaddr, uint32_t serveraddr)
|
||||
{
|
||||
uint8_t *x;
|
||||
|
||||
x = init_dhcp_msg(msg, DHCPREQUEST, hwaddr, xid);
|
||||
|
||||
*x++ = OPT_PARAMETER_LIST;
|
||||
*x++ = 4;
|
||||
*x++ = OPT_SUBNET_MASK;
|
||||
*x++ = OPT_GATEWAY;
|
||||
*x++ = OPT_DNS;
|
||||
*x++ = OPT_BROADCAST_ADDR;
|
||||
|
||||
*x++ = OPT_REQUESTED_IP;
|
||||
*x++ = 4;
|
||||
memcpy(x, &ipaddr, 4);
|
||||
x += 4;
|
||||
|
||||
*x++ = OPT_SERVER_ID;
|
||||
*x++ = 4;
|
||||
memcpy(x, &serveraddr, 4);
|
||||
x += 4;
|
||||
|
||||
*x++ = OPT_END;
|
||||
|
||||
return DHCP_MSG_FIXED_SIZE + (x - msg->options);
|
||||
}
|
||||
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _WIFI_DHCP_H_
|
||||
#define _WIFI_DHCP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PORT_BOOTP_SERVER 67
|
||||
#define PORT_BOOTP_CLIENT 68
|
||||
|
||||
/* RFC 2131 p 9 */
|
||||
typedef struct dhcp_msg dhcp_msg;
|
||||
|
||||
#define OP_BOOTREQUEST 1
|
||||
#define OP_BOOTREPLY 2
|
||||
|
||||
#define FLAGS_BROADCAST 0x8000
|
||||
|
||||
#define HTYPE_ETHER 1
|
||||
|
||||
struct dhcp_msg
|
||||
{
|
||||
uint8_t op; /* BOOTREQUEST / BOOTREPLY */
|
||||
uint8_t htype; /* hw addr type */
|
||||
uint8_t hlen; /* hw addr len */
|
||||
uint8_t hops; /* client set to 0 */
|
||||
|
||||
uint32_t xid; /* transaction id */
|
||||
|
||||
uint16_t secs; /* seconds since start of acq */
|
||||
uint16_t flags;
|
||||
|
||||
uint32_t ciaddr; /* client IP addr */
|
||||
uint32_t yiaddr; /* your (client) IP addr */
|
||||
uint32_t siaddr; /* ip addr of next server */
|
||||
/* (DHCPOFFER and DHCPACK) */
|
||||
uint32_t giaddr; /* relay agent IP addr */
|
||||
|
||||
uint8_t chaddr[16]; /* client hw addr */
|
||||
char sname[64]; /* asciiz server hostname */
|
||||
char file[128]; /* asciiz boot file name */
|
||||
|
||||
uint8_t options[1024]; /* optional parameters */
|
||||
};
|
||||
|
||||
#define DHCP_MSG_FIXED_SIZE 236
|
||||
|
||||
/* first four bytes of options are a cookie to indicate that
|
||||
** the payload are DHCP options as opposed to some other BOOTP
|
||||
** extension.
|
||||
*/
|
||||
#define OPT_COOKIE1 0x63
|
||||
#define OPT_COOKIE2 0x82
|
||||
#define OPT_COOKIE3 0x53
|
||||
#define OPT_COOKIE4 0x63
|
||||
|
||||
/* BOOTP/DHCP options - see RFC 2132 */
|
||||
#define OPT_PAD 0
|
||||
|
||||
#define OPT_SUBNET_MASK 1 /* 4 <ipaddr> */
|
||||
#define OPT_TIME_OFFSET 2 /* 4 <seconds> */
|
||||
#define OPT_GATEWAY 3 /* 4*n <ipaddr> * n */
|
||||
#define OPT_DNS 6 /* 4*n <ipaddr> * n */
|
||||
#define OPT_DOMAIN_NAME 15 /* n <domainnamestring> */
|
||||
#define OPT_BROADCAST_ADDR 28 /* 4 <ipaddr> */
|
||||
|
||||
#define OPT_REQUESTED_IP 50 /* 4 <ipaddr> */
|
||||
#define OPT_LEASE_TIME 51 /* 4 <seconds> */
|
||||
#define OPT_MESSAGE_TYPE 53 /* 1 <msgtype> */
|
||||
#define OPT_SERVER_ID 54 /* 4 <ipaddr> */
|
||||
#define OPT_PARAMETER_LIST 55 /* n <optcode> * n */
|
||||
#define OPT_MESSAGE 56 /* n <errorstring> */
|
||||
#define OPT_CLASS_ID 60 /* n <opaque> */
|
||||
#define OPT_CLIENT_ID 61 /* n <opaque> */
|
||||
#define OPT_END 255
|
||||
|
||||
/* DHCP message types */
|
||||
#define DHCPDISCOVER 1
|
||||
#define DHCPOFFER 2
|
||||
#define DHCPREQUEST 3
|
||||
#define DHCPDECLINE 4
|
||||
#define DHCPACK 5
|
||||
#define DHCPNAK 6
|
||||
#define DHCPRELEASE 7
|
||||
#define DHCPINFORM 8
|
||||
|
||||
int init_dhcp_discover_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid);
|
||||
|
||||
int init_dhcp_request_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid,
|
||||
uint32_t ipaddr, uint32_t serveraddr);
|
||||
|
||||
#endif
|
||||
@ -1,247 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dhcpmsg.h"
|
||||
|
||||
int fatal();
|
||||
|
||||
int open_raw_socket(const char *ifname __attribute__((unused)), uint8_t *hwaddr, int if_index)
|
||||
{
|
||||
int s;
|
||||
struct sockaddr_ll bindaddr;
|
||||
|
||||
if((s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
|
||||
return fatal("socket(PF_PACKET)");
|
||||
}
|
||||
|
||||
memset(&bindaddr, 0, sizeof(bindaddr));
|
||||
bindaddr.sll_family = AF_PACKET;
|
||||
bindaddr.sll_protocol = htons(ETH_P_IP);
|
||||
bindaddr.sll_halen = ETH_ALEN;
|
||||
memcpy(bindaddr.sll_addr, hwaddr, ETH_ALEN);
|
||||
bindaddr.sll_ifindex = if_index;
|
||||
|
||||
if (bind(s, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
|
||||
return fatal("Cannot bind raw socket to interface");
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint32_t checksum(void *buffer, unsigned int count, uint32_t startsum)
|
||||
{
|
||||
uint16_t *up = (uint16_t *)buffer;
|
||||
uint32_t sum = startsum;
|
||||
uint32_t upper16;
|
||||
|
||||
while (count > 1) {
|
||||
sum += *up++;
|
||||
count -= 2;
|
||||
}
|
||||
if (count > 0) {
|
||||
sum += (uint16_t) *(uint8_t *)up;
|
||||
}
|
||||
while ((upper16 = (sum >> 16)) != 0) {
|
||||
sum = (sum & 0xffff) + upper16;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint32_t finish_sum(uint32_t sum)
|
||||
{
|
||||
return ~sum & 0xffff;
|
||||
}
|
||||
|
||||
int send_packet(int s, int if_index, struct dhcp_msg *msg, int size,
|
||||
uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport)
|
||||
{
|
||||
struct iphdr ip;
|
||||
struct udphdr udp;
|
||||
struct iovec iov[3];
|
||||
uint32_t udpsum;
|
||||
uint16_t temp;
|
||||
struct msghdr msghdr;
|
||||
struct sockaddr_ll destaddr;
|
||||
|
||||
ip.version = IPVERSION;
|
||||
ip.ihl = sizeof(ip) >> 2;
|
||||
ip.tos = 0;
|
||||
ip.tot_len = htons(sizeof(ip) + sizeof(udp) + size);
|
||||
ip.id = 0;
|
||||
ip.frag_off = 0;
|
||||
ip.ttl = IPDEFTTL;
|
||||
ip.protocol = IPPROTO_UDP;
|
||||
ip.check = 0;
|
||||
ip.saddr = saddr;
|
||||
ip.daddr = daddr;
|
||||
ip.check = finish_sum(checksum(&ip, sizeof(ip), 0));
|
||||
|
||||
udp.source = htons(sport);
|
||||
udp.dest = htons(dport);
|
||||
udp.len = htons(sizeof(udp) + size);
|
||||
udp.check = 0;
|
||||
|
||||
/* Calculate checksum for pseudo header */
|
||||
udpsum = checksum(&ip.saddr, sizeof(ip.saddr), 0);
|
||||
udpsum = checksum(&ip.daddr, sizeof(ip.daddr), udpsum);
|
||||
temp = htons(IPPROTO_UDP);
|
||||
udpsum = checksum(&temp, sizeof(temp), udpsum);
|
||||
temp = udp.len;
|
||||
udpsum = checksum(&temp, sizeof(temp), udpsum);
|
||||
|
||||
/* Add in the checksum for the udp header */
|
||||
udpsum = checksum(&udp, sizeof(udp), udpsum);
|
||||
|
||||
/* Add in the checksum for the data */
|
||||
udpsum = checksum(msg, size, udpsum);
|
||||
udp.check = finish_sum(udpsum);
|
||||
|
||||
iov[0].iov_base = (char *)&ip;
|
||||
iov[0].iov_len = sizeof(ip);
|
||||
iov[1].iov_base = (char *)&udp;
|
||||
iov[1].iov_len = sizeof(udp);
|
||||
iov[2].iov_base = (char *)msg;
|
||||
iov[2].iov_len = size;
|
||||
memset(&destaddr, 0, sizeof(destaddr));
|
||||
destaddr.sll_family = AF_PACKET;
|
||||
destaddr.sll_protocol = htons(ETH_P_IP);
|
||||
destaddr.sll_ifindex = if_index;
|
||||
destaddr.sll_halen = ETH_ALEN;
|
||||
memcpy(destaddr.sll_addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN);
|
||||
|
||||
msghdr.msg_name = &destaddr;
|
||||
msghdr.msg_namelen = sizeof(destaddr);
|
||||
msghdr.msg_iov = iov;
|
||||
msghdr.msg_iovlen = sizeof(iov) / sizeof(struct iovec);
|
||||
msghdr.msg_flags = 0;
|
||||
msghdr.msg_control = 0;
|
||||
msghdr.msg_controllen = 0;
|
||||
return sendmsg(s, &msghdr, 0);
|
||||
}
|
||||
|
||||
int receive_packet(int s, struct dhcp_msg *msg)
|
||||
{
|
||||
int nread;
|
||||
int is_valid;
|
||||
struct dhcp_packet {
|
||||
struct iphdr ip;
|
||||
struct udphdr udp;
|
||||
struct dhcp_msg dhcp;
|
||||
} packet;
|
||||
int dhcp_size;
|
||||
uint32_t sum;
|
||||
uint16_t temp;
|
||||
uint32_t saddr, daddr;
|
||||
|
||||
nread = read(s, &packet, sizeof(packet));
|
||||
if (nread < 0) {
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* The raw packet interface gives us all packets received by the
|
||||
* network interface. We need to filter out all packets that are
|
||||
* not meant for us.
|
||||
*/
|
||||
is_valid = 0;
|
||||
if (nread < (int)(sizeof(struct iphdr) + sizeof(struct udphdr))) {
|
||||
#if VERBOSE
|
||||
ALOGD("Packet is too small (%d) to be a UDP datagram", nread);
|
||||
#endif
|
||||
} else if (packet.ip.version != IPVERSION || packet.ip.ihl != (sizeof(packet.ip) >> 2)) {
|
||||
#if VERBOSE
|
||||
ALOGD("Not a valid IP packet");
|
||||
#endif
|
||||
} else if (nread < ntohs(packet.ip.tot_len)) {
|
||||
#if VERBOSE
|
||||
ALOGD("Packet was truncated (read %d, needed %d)", nread, ntohs(packet.ip.tot_len));
|
||||
#endif
|
||||
} else if (packet.ip.protocol != IPPROTO_UDP) {
|
||||
#if VERBOSE
|
||||
ALOGD("IP protocol (%d) is not UDP", packet.ip.protocol);
|
||||
#endif
|
||||
} else if (packet.udp.dest != htons(PORT_BOOTP_CLIENT)) {
|
||||
#if VERBOSE
|
||||
ALOGD("UDP dest port (%d) is not DHCP client", ntohs(packet.udp.dest));
|
||||
#endif
|
||||
} else {
|
||||
is_valid = 1;
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Seems like it's probably a valid DHCP packet */
|
||||
/* validate IP header checksum */
|
||||
sum = finish_sum(checksum(&packet.ip, sizeof(packet.ip), 0));
|
||||
if (sum != 0) {
|
||||
printf("IP header checksum failure (0x%x)\n", packet.ip.check);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Validate the UDP checksum.
|
||||
* Since we don't need the IP header anymore, we "borrow" it
|
||||
* to construct the pseudo header used in the checksum calculation.
|
||||
*/
|
||||
dhcp_size = ntohs(packet.udp.len) - sizeof(packet.udp);
|
||||
/*
|
||||
* check validity of dhcp_size.
|
||||
* 1) cannot be negative or zero.
|
||||
* 2) src buffer contains enough bytes to copy
|
||||
* 3) cannot exceed destination buffer
|
||||
*/
|
||||
if ((dhcp_size <= 0) ||
|
||||
((int)(nread - sizeof(struct iphdr) - sizeof(struct udphdr)) < dhcp_size) ||
|
||||
((int)sizeof(struct dhcp_msg) < dhcp_size)) {
|
||||
#if VERBOSE
|
||||
printf("Malformed Packet\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
saddr = packet.ip.saddr;
|
||||
daddr = packet.ip.daddr;
|
||||
nread = ntohs(packet.ip.tot_len);
|
||||
memset(&packet.ip, 0, sizeof(packet.ip));
|
||||
packet.ip.saddr = saddr;
|
||||
packet.ip.daddr = daddr;
|
||||
packet.ip.protocol = IPPROTO_UDP;
|
||||
packet.ip.tot_len = packet.udp.len;
|
||||
temp = packet.udp.check;
|
||||
packet.udp.check = 0;
|
||||
sum = finish_sum(checksum(&packet, nread, 0));
|
||||
packet.udp.check = temp;
|
||||
if (!sum)
|
||||
sum = finish_sum(sum);
|
||||
if (temp != sum) {
|
||||
printf("UDP header checksum failure (0x%x should be 0x%x)\n", sum, temp);
|
||||
return -1;
|
||||
}
|
||||
memcpy(msg, &packet.dhcp, dhcp_size);
|
||||
return dhcp_size;
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _WIFI_PACKET_H_
|
||||
#define _WIFI_PACKET_H_
|
||||
|
||||
int open_raw_socket(const char *ifname, uint8_t *hwaddr, int if_index);
|
||||
int send_packet(int s, int if_index, struct dhcp_msg *msg, int size,
|
||||
uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport);
|
||||
int receive_packet(int s, struct dhcp_msg *msg);
|
||||
|
||||
#endif
|
||||
@ -1,748 +0,0 @@
|
||||
/* This example is placed in the public domain. */
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
#include <net/if.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
//#include <linux/if.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
#include "ifutils.h"
|
||||
|
||||
#define ERRMSG(v...) printf("%s-%d: error=%s %s\n", __func__, __LINE__, strerror(errno), ##v)
|
||||
extern void dbg_time(const char *fmt, ...);
|
||||
int mask_to_prefix_v4(uint32_t mask)
|
||||
{
|
||||
int ret = 0;
|
||||
while (mask)
|
||||
{
|
||||
mask = mask & (mask - 1);
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *ipaddr_to_string_v4(in_addr_t ipaddr)
|
||||
{
|
||||
static char buf[INET6_ADDRSTRLEN] = {'\0'};
|
||||
buf[0] = '\0';
|
||||
uint32_t addr = ipaddr;
|
||||
return inet_ntop(AF_INET, &addr, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
const char *ipaddr_to_string_v6(uint8_t *ipaddr)
|
||||
{
|
||||
static char buf[INET6_ADDRSTRLEN] = {'\0'};
|
||||
buf[0] = '\0';
|
||||
return inet_ntop(AF_INET6, ipaddr, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static void ifc_init_ifr(const char *name, struct ifreq *ifr)
|
||||
{
|
||||
memset(ifr, 0, sizeof(struct ifreq));
|
||||
strncpy(ifr->ifr_name, name, IFNAMSIZ);
|
||||
ifr->ifr_name[IFNAMSIZ - 1] = 0;
|
||||
}
|
||||
|
||||
int if_get_hwaddr(const char *name, void *ptr)
|
||||
{
|
||||
int r;
|
||||
struct ifreq ifr;
|
||||
ifc_init_ifr(name, &ifr);
|
||||
|
||||
int ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (ifc_ctl_sock < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int if_act_on_link(const char *ifname, int state)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
struct ifinfomsg *ifm;
|
||||
int ret;
|
||||
unsigned int seq, portid, change = 0, flags = 0;
|
||||
static int oldstate = -1;
|
||||
|
||||
if (state == oldstate)
|
||||
return 0;
|
||||
oldstate = state;
|
||||
|
||||
if (state)
|
||||
{
|
||||
change |= IFF_UP;
|
||||
flags |= IFF_UP;
|
||||
}
|
||||
else
|
||||
{
|
||||
change |= IFF_UP;
|
||||
flags &= ~IFF_UP;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = RTM_NEWLINK;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
|
||||
ifm->ifi_family = AF_UNSPEC;
|
||||
ifm->ifi_change = change;
|
||||
ifm->ifi_flags = flags;
|
||||
|
||||
mnl_attr_put_str(nlh, IFLA_IFNAME, ifname);
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG("mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" mnl_socket_recvfrom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" mnl_cb_run");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_link_up(const char *ifname)
|
||||
{
|
||||
dbg_time("if_link_up %s",ifname);
|
||||
return if_act_on_link(ifname, 1);
|
||||
}
|
||||
|
||||
int if_link_down(const char *ifname)
|
||||
{
|
||||
|
||||
dbg_time("if_link_down %s",ifname);
|
||||
return if_act_on_link(ifname, 0);
|
||||
}
|
||||
|
||||
int if_set_mtu(const char *ifname, uint32_t mtu)
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
unsigned int seq, portid;
|
||||
struct mnl_socket *nl;
|
||||
struct nlmsghdr *nlh;
|
||||
struct ifinfomsg *ifm;
|
||||
int ret;
|
||||
int iface;
|
||||
static uint32_t oldmtu = 1500;
|
||||
|
||||
if (mtu == oldmtu)
|
||||
return 0;
|
||||
oldmtu = mtu;
|
||||
|
||||
iface = if_nametoindex(ifname);
|
||||
if (iface == 0)
|
||||
{
|
||||
ERRMSG(" if_nametoindex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = RTM_NEWLINK;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifinfomsg));
|
||||
ifm->ifi_family = AF_UNSPEC;
|
||||
ifm->ifi_index = iface;
|
||||
ifm->ifi_change = 0xFFFFFFFF;
|
||||
ifm->ifi_type = 0;
|
||||
ifm->ifi_flags = IFF_NOARP | IFF_MULTICAST;
|
||||
|
||||
mnl_attr_put_u32(nlh, IFLA_MTU, mtu);
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG(" mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" mnl_socket_recvfrom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" mnl_cb_run");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the ip addr object
|
||||
*
|
||||
* @param operate
|
||||
* 0 -> add address on interface
|
||||
* 1 -> delete address on interface
|
||||
* @param ifname
|
||||
* @param ipaddr
|
||||
* @param prefix
|
||||
* @return int
|
||||
*/
|
||||
static int if_act_on_addr(bool operate, int proto, const char *ifname, addr_t *ipaddr, uint32_t prefix)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
struct ifaddrmsg *ifm;
|
||||
uint32_t seq, portid;
|
||||
int ret, family = proto;
|
||||
|
||||
int iface;
|
||||
|
||||
iface = if_nametoindex(ifname);
|
||||
if (iface == 0)
|
||||
{
|
||||
ERRMSG(" if_nametoindex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
if (operate)
|
||||
nlh->nlmsg_type = RTM_NEWADDR;
|
||||
else
|
||||
nlh->nlmsg_type = RTM_DELADDR;
|
||||
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
|
||||
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifaddrmsg));
|
||||
|
||||
ifm->ifa_family = family;
|
||||
ifm->ifa_prefixlen = prefix;
|
||||
ifm->ifa_flags = IFA_F_PERMANENT;
|
||||
|
||||
ifm->ifa_scope = RT_SCOPE_UNIVERSE;
|
||||
ifm->ifa_index = iface;
|
||||
|
||||
/*
|
||||
* The exact meaning of IFA_LOCAL and IFA_ADDRESS depend
|
||||
* on the address family being used and the device type.
|
||||
* For broadcast devices (like the interfaces we use),
|
||||
* for IPv4 we specify both and they are used interchangeably.
|
||||
* For IPv6, only IFA_ADDRESS needs to be set.
|
||||
*/
|
||||
if (family == AF_INET)
|
||||
{
|
||||
mnl_attr_put_u32(nlh, IFA_LOCAL, ipaddr->ip);
|
||||
mnl_attr_put_u32(nlh, IFA_ADDRESS, ipaddr->ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
mnl_attr_put(nlh, IFA_ADDRESS, sizeof(struct in6_addr), ipaddr);
|
||||
}
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG(" mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_recvfrom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" mnl_cb_run");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_set_addr_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix)
|
||||
{
|
||||
addr_t addr;
|
||||
addr.ip = ipaddr;
|
||||
return if_act_on_addr(1, AF_INET, ifname, &addr, prefix);
|
||||
}
|
||||
|
||||
int if_del_addr_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix)
|
||||
{
|
||||
addr_t addr;
|
||||
addr.ip = ipaddr;
|
||||
return if_act_on_addr(0, AF_INET, ifname, &addr, prefix);
|
||||
}
|
||||
|
||||
int if_set_addr_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix)
|
||||
{
|
||||
addr_t addr;
|
||||
memcpy(&addr.ip6, ipaddr, 16);
|
||||
return if_act_on_addr(1, AF_INET6, ifname, &addr, prefix);
|
||||
}
|
||||
|
||||
int if_del_addr_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix)
|
||||
{
|
||||
addr_t addr;
|
||||
memcpy(&addr.ip6, ipaddr, 16);
|
||||
return if_act_on_addr(0, AF_INET6, ifname, &addr, prefix);
|
||||
}
|
||||
|
||||
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||
{
|
||||
const struct nlattr **tb = data;
|
||||
int type = mnl_attr_get_type(attr);
|
||||
|
||||
/* skip unsupported attribute in user-space */
|
||||
if (mnl_attr_type_valid(attr, IFA_MAX) < 0)
|
||||
return MNL_CB_OK;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_attr_validate");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tb[type] = attr;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[IFA_MAX + 1] = {};
|
||||
struct ifaddrmsg *ifa = mnl_nlmsg_get_payload(nlh);
|
||||
struct addrinfo_t *addrinfo = (struct addrinfo_t *)data;
|
||||
void *addr = NULL;
|
||||
|
||||
mnl_attr_parse(nlh, sizeof(*ifa), data_attr_cb, tb);
|
||||
if (tb[IFA_ADDRESS])
|
||||
{
|
||||
char out[INET6_ADDRSTRLEN];
|
||||
|
||||
addr = mnl_attr_get_payload(tb[IFLA_ADDRESS]);
|
||||
addr = mnl_attr_get_payload(tb[IFA_ADDRESS]);
|
||||
if (!inet_ntop(ifa->ifa_family, addr, out, sizeof(out)))
|
||||
ERRMSG("inet_ntop");
|
||||
// printf("%d %d-> %d %s\n", addrinfo->iface, ifa->ifa_index, ifa->ifa_scope, out);
|
||||
|
||||
addrinfo->addrs[addrinfo->num].prefix = ifa->ifa_prefixlen;
|
||||
if (ifa->ifa_index == addrinfo->iface)
|
||||
{
|
||||
if (ifa->ifa_family == AF_INET6)
|
||||
memcpy(addrinfo->addrs[addrinfo->num].address.ip6.s6_addr, addr, 16);
|
||||
if (ifa->ifa_family == AF_INET)
|
||||
memcpy(&(addrinfo->addrs[addrinfo->num].address.ip), addr, 4);
|
||||
addrinfo->num++;
|
||||
}
|
||||
}
|
||||
|
||||
// ifa->ifa_scope
|
||||
// 0: global
|
||||
// 200: site
|
||||
// 253: link
|
||||
// 254: host
|
||||
// 255: nowhere
|
||||
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param ifname
|
||||
* @param proto
|
||||
* AF_INET -> for IPv4
|
||||
* AF_INET6 -> for IPv6
|
||||
* @return int
|
||||
*/
|
||||
static int if_get_addr(const char *ifname, int proto, struct addrinfo_t *addrinfo)
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
unsigned int seq, portid;
|
||||
struct mnl_socket *nl;
|
||||
struct nlmsghdr *nlh;
|
||||
struct rtgenmsg *rt;
|
||||
int ret;
|
||||
|
||||
addrinfo->iface = if_nametoindex(ifname);
|
||||
if (addrinfo->iface == 0)
|
||||
{
|
||||
ERRMSG(" if_nametoindex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = RTM_GETADDR;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg));
|
||||
if (proto == AF_INET)
|
||||
rt->rtgen_family = AF_INET;
|
||||
else if (proto == AF_INET6)
|
||||
rt->rtgen_family = AF_INET6;
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG(" mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
while (ret > 0)
|
||||
{
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, addrinfo);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
}
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" error");
|
||||
return -1;
|
||||
}
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_flush_v4_addr(const char *ifname)
|
||||
{
|
||||
struct addrinfo_t addrinfo;
|
||||
int i = 0;
|
||||
|
||||
memset(&addrinfo, 0, sizeof(struct addrinfo_t));
|
||||
if_get_addr(ifname, AF_INET, &addrinfo);
|
||||
for (; i < addrinfo.num; i++)
|
||||
{
|
||||
// printf("remove address: %s\n", ipaddr_to_string_v4(addrinfo.addrs[i].address.ip));
|
||||
if_del_addr_v4(ifname, addrinfo.addrs[i].address.ip, addrinfo.addrs[i].prefix);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_flush_v6_addr(const char *ifname)
|
||||
{
|
||||
struct addrinfo_t addrinfo;
|
||||
int i = 0;
|
||||
|
||||
memset(&addrinfo, 0, sizeof(struct addrinfo_t));
|
||||
if_get_addr(ifname, AF_INET6, &addrinfo);
|
||||
for (; i < addrinfo.num; i++)
|
||||
{
|
||||
// printf("remove address: %s\n", ipaddr_to_string_v6(addrinfo.addrs[i].address.ip6.s6_addr));
|
||||
if_del_addr_v6(ifname, addrinfo.addrs[i].address.ip6.s6_addr, addrinfo.addrs[i].prefix);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the route addr object
|
||||
* Usage:
|
||||
* iface destination cidr [gateway]
|
||||
* Example:
|
||||
* eth0 10.0.1.12 32 10.0.1.11
|
||||
* eth0 ffff::10.0.1.12 128 fdff::1
|
||||
* @param operate
|
||||
* add or del
|
||||
* @param ifname
|
||||
* @param dstaddr
|
||||
* @param prefix
|
||||
* @param gwaddr
|
||||
* @return int
|
||||
*/
|
||||
int if_act_on_route(bool operate, int proto, const char *ifname, addr_t *dstaddr, uint32_t prefix, addr_t *gwaddr)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
struct rtmsg *rtm;
|
||||
uint32_t seq, portid;
|
||||
int iface, ret, family = proto;
|
||||
|
||||
iface = if_nametoindex(ifname);
|
||||
if (iface == 0)
|
||||
{
|
||||
ERRMSG(" if_nametoindex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
if (operate)
|
||||
nlh->nlmsg_type = RTM_NEWROUTE;
|
||||
else
|
||||
nlh->nlmsg_type = RTM_DELROUTE;
|
||||
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
|
||||
rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg));
|
||||
rtm->rtm_family = family;
|
||||
rtm->rtm_dst_len = prefix;
|
||||
rtm->rtm_src_len = 0;
|
||||
rtm->rtm_tos = 0;
|
||||
rtm->rtm_protocol = RTPROT_STATIC;
|
||||
rtm->rtm_table = RT_TABLE_MAIN;
|
||||
rtm->rtm_type = RTN_UNICAST;
|
||||
/* is there any gateway? */
|
||||
rtm->rtm_scope = gwaddr ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
|
||||
rtm->rtm_flags = 0;
|
||||
|
||||
if (family == AF_INET)
|
||||
mnl_attr_put_u32(nlh, RTA_DST, dstaddr->ip);
|
||||
else
|
||||
mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), dstaddr);
|
||||
|
||||
mnl_attr_put_u32(nlh, RTA_OIF, iface);
|
||||
if (gwaddr)
|
||||
{
|
||||
if (family == AF_INET)
|
||||
mnl_attr_put_u32(nlh, RTA_GATEWAY, gwaddr->ip);
|
||||
else
|
||||
{
|
||||
mnl_attr_put(nlh, RTA_GATEWAY, sizeof(struct in6_addr), gwaddr);
|
||||
}
|
||||
}
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG(" mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_recvfrom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" mnl_cb_run");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_set_default_route_v4(const char *ifname)
|
||||
{
|
||||
return if_act_on_route(1, AF_INET, ifname, (addr_t *)&in6addr_any, 0, NULL);
|
||||
}
|
||||
|
||||
int if_del_default_route_v4(const char *ifname)
|
||||
{
|
||||
return if_act_on_route(0, AF_INET, ifname, (addr_t *)&in6addr_any, 0, NULL);
|
||||
}
|
||||
|
||||
int if_set_default_route_v6(const char *ifname)
|
||||
{
|
||||
return if_act_on_route(1, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, NULL);
|
||||
}
|
||||
|
||||
int if_del_default_route_v6(const char *ifname)
|
||||
{
|
||||
return if_act_on_route(0, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the default gwaddr object
|
||||
* set default gw
|
||||
* @param operate
|
||||
* @param ifname
|
||||
* @param gwaddr
|
||||
* gateway ip
|
||||
* @return int
|
||||
*/
|
||||
int if_set_route_gw_v4(const char *ifname, in_addr_t gwaddr)
|
||||
{
|
||||
addr_t addr;
|
||||
memset(&addr, 0, sizeof(addr_t));
|
||||
addr.ip = gwaddr;
|
||||
return if_act_on_route(1, AF_INET, ifname, (addr_t *)&in6addr_any, 0, &addr);
|
||||
}
|
||||
|
||||
int if_del_route_gw_v4(const char *ifname, in_addr_t gwaddr)
|
||||
{
|
||||
addr_t addr;
|
||||
memset(&addr, 0, sizeof(addr_t));
|
||||
addr.ip = gwaddr;
|
||||
return if_act_on_route(0, AF_INET, ifname, (addr_t *)&in6addr_any, 0, &addr);
|
||||
}
|
||||
|
||||
int if_set_route_gw_v6(const char *ifname, uint8_t *gwaddr)
|
||||
{
|
||||
addr_t addr;
|
||||
memset(&addr, 0, sizeof(addr_t));
|
||||
memcpy(&addr.ip6, gwaddr, 16);
|
||||
return if_act_on_route(1, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, &addr);
|
||||
}
|
||||
|
||||
int if_del_route_gw_v6(const char *ifname, uint8_t *gwaddr)
|
||||
{
|
||||
addr_t addr;
|
||||
memset(&addr, 0, sizeof(addr_t));
|
||||
memcpy(&addr.ip6, gwaddr, 16);
|
||||
return if_act_on_route(0, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, &addr);
|
||||
}
|
||||
|
||||
int if_set_dns(const char *dns1, const char *dns2)
|
||||
{
|
||||
int ret = 0;
|
||||
char buf[128] = {'\0'};
|
||||
int fd = open("/etc/resolv.conf", O_CREAT | O_WRONLY | O_TRUNC);
|
||||
if (fd < 0)
|
||||
{
|
||||
ERRMSG(" fail to open /etc/resolv.conf");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dns1)
|
||||
snprintf(buf, sizeof(buf), "nameserver %s\n", dns1);
|
||||
if (dns2)
|
||||
snprintf(buf, sizeof(buf), "nameserver %s\n", dns2);
|
||||
ret = write(fd, buf, strlen(buf));
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" write dns");
|
||||
}
|
||||
close(fd);
|
||||
return ret > 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
int if_set_network_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix,
|
||||
in_addr_t gwaddr, in_addr_t dns1, in_addr_t dns2)
|
||||
{
|
||||
if_link_up(ifname);
|
||||
sleep(2);
|
||||
if_set_addr_v4(ifname, ipaddr, prefix);
|
||||
if_set_default_route_v4(ifname);
|
||||
if_set_dns(ipaddr_to_string_v4(dns1), ipaddr_to_string_v4(dns2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_set_network_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix,
|
||||
uint8_t *gwaddr, uint8_t *dns1, uint8_t *dns2)
|
||||
{
|
||||
if_link_up(ifname);
|
||||
sleep(2);
|
||||
if_set_addr_v6(ifname, ipaddr, prefix);
|
||||
if_set_default_route_v6(ifname);
|
||||
if_set_dns(ipaddr_to_string_v6(dns1), ipaddr_to_string_v6(dns2));
|
||||
return 0;
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
#ifndef __IFUTILS_H__
|
||||
#define __IFUTILS_H__
|
||||
|
||||
typedef union {
|
||||
in_addr_t ip;
|
||||
struct in6_addr ip6;
|
||||
} addr_t;
|
||||
|
||||
#define MAX_IP_NUM 32
|
||||
struct addrinfo_t
|
||||
{
|
||||
int iface;
|
||||
int num;
|
||||
struct
|
||||
{
|
||||
int prefix;
|
||||
addr_t address;
|
||||
} addrs[MAX_IP_NUM];
|
||||
};
|
||||
|
||||
const char *ipaddr_to_string_v4(in_addr_t ipaddr);
|
||||
const char *ipaddr_to_string_v6(uint8_t *ipaddr);
|
||||
int mask_to_prefix_v4(in_addr_t mask);
|
||||
|
||||
int if_get_hwaddr(const char *name, void *ptr);
|
||||
|
||||
int if_link_down(const char *ifname);
|
||||
int if_link_up(const char *ifname);
|
||||
int if_set_mtu(const char *ifname, uint32_t mtu);
|
||||
|
||||
int if_set_addr_v4(const char *name, in_addr_t address, uint32_t prefixlen);
|
||||
int if_del_addr_v4(const char *name, in_addr_t address, uint32_t prefixlen);
|
||||
int if_set_addr_v6(const char *name, uint8_t *address, uint32_t prefixlen);
|
||||
int if_del_addr_v6(const char *name, uint8_t *address, uint32_t prefixlen);
|
||||
int if_flush_v4_addr(const char *ifname);
|
||||
int if_flush_v6_addr(const char *ifname);
|
||||
|
||||
int if_set_route_gw_v4(const char *ifname, in_addr_t gwaddr);
|
||||
int if_del_route_gw_v4(const char *ifname, in_addr_t gwaddr);
|
||||
int if_set_default_route_v4(const char *ifname);
|
||||
int if_del_default_route_v4(const char *ifname);
|
||||
|
||||
int if_set_route_gw_v6(const char *ifname, uint8_t *gwaddr);
|
||||
int if_del_route_gw_v6(const char *ifname, uint8_t *gwaddr);
|
||||
int if_set_default_route_v6(const char *ifname);
|
||||
int if_del_default_route_v6(const char *ifname);
|
||||
|
||||
int if_set_network_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix,
|
||||
in_addr_t gwaddr, in_addr_t dns1, in_addr_t dns2);
|
||||
int if_set_network_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix,
|
||||
uint8_t *gwaddr, uint8_t *dns1, uint8_t *dns2);
|
||||
|
||||
#endif //__IFUTILS_H__
|
||||
@ -1,202 +0,0 @@
|
||||
#ifndef _LIBMNL_H_
|
||||
#define _LIBMNL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h> /* for sa_family_t */
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Netlink socket API
|
||||
*/
|
||||
|
||||
#define MNL_SOCKET_AUTOPID 0
|
||||
#define MNL_SOCKET_BUFFER_SIZE (sysconf(_SC_PAGESIZE) < 8192L ? sysconf(_SC_PAGESIZE) : 8192L)
|
||||
#define MNL_SOCKET_DUMP_SIZE 32768
|
||||
|
||||
struct mnl_socket;
|
||||
|
||||
extern struct mnl_socket *mnl_socket_open(int bus);
|
||||
extern struct mnl_socket *mnl_socket_open2(int bus, int flags);
|
||||
extern struct mnl_socket *mnl_socket_fdopen(int fd);
|
||||
extern int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid);
|
||||
extern int mnl_socket_close(struct mnl_socket *nl);
|
||||
extern int mnl_socket_get_fd(const struct mnl_socket *nl);
|
||||
extern unsigned int mnl_socket_get_portid(const struct mnl_socket *nl);
|
||||
extern ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *req, size_t siz);
|
||||
extern ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t siz);
|
||||
extern int mnl_socket_setsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t len);
|
||||
extern int mnl_socket_getsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t *len);
|
||||
|
||||
/*
|
||||
* Netlink message API
|
||||
*/
|
||||
|
||||
#define MNL_ALIGNTO 4
|
||||
#define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1))
|
||||
#define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr))
|
||||
|
||||
extern size_t mnl_nlmsg_size(size_t len);
|
||||
extern size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh);
|
||||
|
||||
/* Netlink message header builder */
|
||||
extern struct nlmsghdr *mnl_nlmsg_put_header(void *buf);
|
||||
extern void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size);
|
||||
|
||||
/* Netlink message iterators */
|
||||
extern bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len);
|
||||
extern struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len);
|
||||
|
||||
/* Netlink sequence tracking */
|
||||
extern bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq);
|
||||
|
||||
/* Netlink portID checking */
|
||||
extern bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid);
|
||||
|
||||
/* Netlink message getters */
|
||||
extern void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh);
|
||||
extern void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset);
|
||||
extern void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh);
|
||||
|
||||
/* Netlink message printer */
|
||||
extern void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, size_t extra_header_size);
|
||||
|
||||
/* Message batch helpers */
|
||||
struct mnl_nlmsg_batch;
|
||||
extern struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf, size_t bufsiz);
|
||||
extern bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b);
|
||||
extern void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b);
|
||||
extern size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b);
|
||||
extern void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b);
|
||||
extern void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b);
|
||||
extern void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b);
|
||||
extern bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b);
|
||||
|
||||
/*
|
||||
* Netlink attributes API
|
||||
*/
|
||||
#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr))
|
||||
|
||||
/* TLV attribute getters */
|
||||
extern uint16_t mnl_attr_get_type(const struct nlattr *attr);
|
||||
extern uint16_t mnl_attr_get_len(const struct nlattr *attr);
|
||||
extern uint16_t mnl_attr_get_payload_len(const struct nlattr *attr);
|
||||
extern void *mnl_attr_get_payload(const struct nlattr *attr);
|
||||
extern uint8_t mnl_attr_get_u8(const struct nlattr *attr);
|
||||
extern uint16_t mnl_attr_get_u16(const struct nlattr *attr);
|
||||
extern uint32_t mnl_attr_get_u32(const struct nlattr *attr);
|
||||
extern uint64_t mnl_attr_get_u64(const struct nlattr *attr);
|
||||
extern const char *mnl_attr_get_str(const struct nlattr *attr);
|
||||
|
||||
/* TLV attribute putters */
|
||||
extern void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data);
|
||||
extern void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data);
|
||||
extern void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data);
|
||||
extern void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data);
|
||||
extern void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data);
|
||||
extern void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data);
|
||||
extern void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data);
|
||||
|
||||
/* TLV attribute putters with buffer boundary checkings */
|
||||
extern bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, size_t len, const void *data);
|
||||
extern bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint8_t data);
|
||||
extern bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint16_t data);
|
||||
extern bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint32_t data);
|
||||
extern bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint64_t data);
|
||||
extern bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data);
|
||||
extern bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data);
|
||||
|
||||
/* TLV attribute nesting */
|
||||
extern struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type);
|
||||
extern struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type);
|
||||
extern void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start);
|
||||
extern void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start);
|
||||
|
||||
/* TLV validation */
|
||||
extern int mnl_attr_type_valid(const struct nlattr *attr, uint16_t maxtype);
|
||||
|
||||
enum mnl_attr_data_type {
|
||||
MNL_TYPE_UNSPEC,
|
||||
MNL_TYPE_U8,
|
||||
MNL_TYPE_U16,
|
||||
MNL_TYPE_U32,
|
||||
MNL_TYPE_U64,
|
||||
MNL_TYPE_STRING,
|
||||
MNL_TYPE_FLAG,
|
||||
MNL_TYPE_MSECS,
|
||||
MNL_TYPE_NESTED,
|
||||
MNL_TYPE_NESTED_COMPAT,
|
||||
MNL_TYPE_NUL_STRING,
|
||||
MNL_TYPE_BINARY,
|
||||
MNL_TYPE_MAX,
|
||||
};
|
||||
|
||||
extern int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type);
|
||||
extern int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t len);
|
||||
|
||||
/* TLV iterators */
|
||||
extern bool mnl_attr_ok(const struct nlattr *attr, int len);
|
||||
extern struct nlattr *mnl_attr_next(const struct nlattr *attr);
|
||||
|
||||
#define mnl_attr_for_each(attr, nlh, offset) \
|
||||
for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \
|
||||
mnl_attr_ok((attr), (char *)mnl_nlmsg_get_payload_tail(nlh) - (char *)(attr)); \
|
||||
(attr) = mnl_attr_next(attr))
|
||||
|
||||
#define mnl_attr_for_each_nested(attr, nest) \
|
||||
for ((attr) = mnl_attr_get_payload(nest); \
|
||||
mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \
|
||||
(attr) = mnl_attr_next(attr))
|
||||
|
||||
#define mnl_attr_for_each_payload(payload, payload_size) \
|
||||
for ((attr) = (payload); \
|
||||
mnl_attr_ok((attr), (char *)(payload) + payload_size - (char *)(attr)); \
|
||||
(attr) = mnl_attr_next(attr))
|
||||
|
||||
/* TLV callback-based attribute parsers */
|
||||
typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);
|
||||
|
||||
extern int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data);
|
||||
extern int mnl_attr_parse_nested(const struct nlattr *attr, mnl_attr_cb_t cb, void *data);
|
||||
extern int mnl_attr_parse_payload(const void *payload, size_t payload_len, mnl_attr_cb_t cb, void *data);
|
||||
|
||||
/*
|
||||
* callback API
|
||||
*/
|
||||
#define MNL_CB_ERROR -1
|
||||
#define MNL_CB_STOP 0
|
||||
#define MNL_CB_OK 1
|
||||
|
||||
typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data);
|
||||
|
||||
extern int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
|
||||
unsigned int portid, mnl_cb_t cb_data, void *data);
|
||||
|
||||
extern int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq,
|
||||
unsigned int portid, mnl_cb_t cb_data, void *data,
|
||||
const mnl_cb_t *cb_ctl_array,
|
||||
unsigned int cb_ctl_array_len);
|
||||
|
||||
/*
|
||||
* other declarations
|
||||
*/
|
||||
|
||||
#ifndef SOL_NETLINK
|
||||
#define SOL_NETLINK 270
|
||||
#endif
|
||||
|
||||
#ifndef MNL_ARRAY_SIZE
|
||||
#define MNL_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,556 +0,0 @@
|
||||
/*
|
||||
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
|
||||
/**
|
||||
* \defgroup nlmsg Netlink message helpers
|
||||
*
|
||||
* Netlink message:
|
||||
* \verbatim
|
||||
|<----------------- 4 bytes ------------------->|
|
||||
|<----- 2 bytes ------>|<------- 2 bytes ------>|
|
||||
|-----------------------------------------------|
|
||||
| Message length (including header) |
|
||||
|-----------------------------------------------|
|
||||
| Message type | Message flags |
|
||||
|-----------------------------------------------|
|
||||
| Message sequence number |
|
||||
|-----------------------------------------------|
|
||||
| Netlink PortID |
|
||||
|-----------------------------------------------|
|
||||
| |
|
||||
. Payload .
|
||||
|_______________________________________________|
|
||||
\endverbatim
|
||||
*
|
||||
* There is usually an extra header after the the Netlink header (at the
|
||||
* beginning of the payload). This extra header is specific of the Netlink
|
||||
* subsystem. After this extra header, it comes the sequence of attributes
|
||||
* that are expressed in Type-Length-Value (TLV) format.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_size - calculate the size of Netlink message (without alignment)
|
||||
* \param len length of the Netlink payload
|
||||
*
|
||||
* This function returns the size of a netlink message (header plus payload)
|
||||
* without alignment.
|
||||
*/
|
||||
size_t mnl_nlmsg_size(size_t len)
|
||||
{
|
||||
return len + MNL_NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_get_payload_len - get the length of the Netlink payload
|
||||
* \param nlh pointer to the header of the Netlink message
|
||||
*
|
||||
* This function returns the Length of the netlink payload, ie. the length
|
||||
* of the full message minus the size of the Netlink header.
|
||||
*/
|
||||
size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return nlh->nlmsg_len - MNL_NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_put_header - reserve and prepare room for Netlink header
|
||||
* \param buf memory already allocated to store the Netlink header
|
||||
*
|
||||
* This function sets to zero the room that is required to put the Netlink
|
||||
* header in the memory buffer passed as parameter. This function also
|
||||
* initializes the nlmsg_len field to the size of the Netlink header. This
|
||||
* function returns a pointer to the Netlink header structure.
|
||||
*/
|
||||
struct nlmsghdr *mnl_nlmsg_put_header(void *buf)
|
||||
{
|
||||
int len = MNL_ALIGN(sizeof(struct nlmsghdr));
|
||||
struct nlmsghdr *nlh = buf;
|
||||
|
||||
memset(buf, 0, len);
|
||||
nlh->nlmsg_len = len;
|
||||
return nlh;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_put_extra_header - reserve and prepare room for an extra header
|
||||
* \param nlh pointer to Netlink header
|
||||
* \param size size of the extra header that we want to put
|
||||
*
|
||||
* This function sets to zero the room that is required to put the extra
|
||||
* header after the initial Netlink header. This function also increases
|
||||
* the nlmsg_len field. You have to invoke mnl_nlmsg_put_header() before
|
||||
* you call this function. This function returns a pointer to the extra
|
||||
* header.
|
||||
*/
|
||||
void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh,
|
||||
size_t size)
|
||||
{
|
||||
char *ptr = (char *)nlh + nlh->nlmsg_len;
|
||||
size_t len = MNL_ALIGN(size);
|
||||
nlh->nlmsg_len += len;
|
||||
memset(ptr, 0, len);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_get_payload - get a pointer to the payload of the netlink message
|
||||
* \param nlh pointer to a netlink header
|
||||
*
|
||||
* This function returns a pointer to the payload of the netlink message.
|
||||
*/
|
||||
void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return (void *)nlh + MNL_NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_get_payload_offset - get a pointer to the payload of the message
|
||||
* \param nlh pointer to a netlink header
|
||||
* \param offset offset to the payload of the attributes TLV set
|
||||
*
|
||||
* This function returns a pointer to the payload of the netlink message plus
|
||||
* a given offset.
|
||||
*/
|
||||
void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh,
|
||||
size_t offset)
|
||||
{
|
||||
return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_ok - check a there is room for netlink message
|
||||
* \param nlh netlink message that we want to check
|
||||
* \param len remaining bytes in a buffer that contains the netlink message
|
||||
*
|
||||
* This function is used to check that a buffer that contains a netlink
|
||||
* message has enough room for the netlink message that it stores, ie. this
|
||||
* function can be used to verify that a netlink message is not malformed nor
|
||||
* truncated.
|
||||
*
|
||||
* This function does not set errno in case of error since it is intended
|
||||
* for iterations. Thus, it returns true on success and false on error.
|
||||
*
|
||||
* The len parameter may become negative in malformed messages during message
|
||||
* iteration, that is why we use a signed integer.
|
||||
*/
|
||||
bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
|
||||
{
|
||||
return len >= (int)sizeof(struct nlmsghdr) &&
|
||||
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||
(int)nlh->nlmsg_len <= len;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_next - get the next netlink message in a multipart message
|
||||
* \param nlh current netlink message that we are handling
|
||||
* \param len length of the remaining bytes in the buffer (passed by reference).
|
||||
*
|
||||
* This function returns a pointer to the next netlink message that is part
|
||||
* of a multi-part netlink message. Netlink can batch several messages into
|
||||
* one buffer so that the receiver has to iterate over the whole set of
|
||||
* Netlink messages.
|
||||
*
|
||||
* You have to use mnl_nlmsg_ok() to check if the next Netlink message is
|
||||
* valid.
|
||||
*/
|
||||
struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh,
|
||||
int *len)
|
||||
{
|
||||
*len -= MNL_ALIGN(nlh->nlmsg_len);
|
||||
return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_get_payload_tail - get the ending of the netlink message
|
||||
* \param nlh pointer to netlink message
|
||||
*
|
||||
* This function returns a pointer to the netlink message tail. This is useful
|
||||
* to build a message since we continue adding attributes at the end of the
|
||||
* message.
|
||||
*/
|
||||
void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_seq_ok - perform sequence tracking
|
||||
* \param nlh current netlink message that we are handling
|
||||
* \param seq last sequence number used to send a message
|
||||
*
|
||||
* This functions returns true if the sequence tracking is fulfilled, otherwise
|
||||
* false is returned. We skip the tracking for netlink messages whose sequence
|
||||
* number is zero since it is usually reserved for event-based kernel
|
||||
* notifications. On the other hand, if seq is set but the message sequence
|
||||
* number is not set (i.e. this is an event message coming from kernel-space),
|
||||
* then we also skip the tracking. This approach is good if we use the same
|
||||
* socket to send commands to kernel-space (that we want to track) and to
|
||||
* listen to events (that we do not track).
|
||||
*/
|
||||
bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh,
|
||||
unsigned int seq)
|
||||
{
|
||||
return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_portid_ok - perform portID origin check
|
||||
* \param nlh current netlink message that we are handling
|
||||
* \param portid netlink portid that we want to check
|
||||
*
|
||||
* This functions returns true if the origin is fulfilled, otherwise
|
||||
* false is returned. We skip the tracking for netlink message whose portID
|
||||
* is zero since it is reserved for event-based kernel notifications. On the
|
||||
* other hand, if portid is set but the message PortID is not (i.e. this
|
||||
* is an event message coming from kernel-space), then we also skip the
|
||||
* tracking. This approach is good if we use the same socket to send commands
|
||||
* to kernel-space (that we want to track) and to listen to events (that we
|
||||
* do not track).
|
||||
*/
|
||||
bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh,
|
||||
unsigned int portid)
|
||||
{
|
||||
return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true;
|
||||
}
|
||||
|
||||
static void mnl_nlmsg_fprintf_header(FILE *fd, const struct nlmsghdr *nlh)
|
||||
{
|
||||
fprintf(fd, "----------------\t------------------\n");
|
||||
fprintf(fd, "| %.010u |\t| message length |\n", nlh->nlmsg_len);
|
||||
fprintf(fd, "| %.05u | %c%c%c%c |\t| type | flags |\n",
|
||||
nlh->nlmsg_type,
|
||||
nlh->nlmsg_flags & NLM_F_REQUEST ? 'R' : '-',
|
||||
nlh->nlmsg_flags & NLM_F_MULTI ? 'M' : '-',
|
||||
nlh->nlmsg_flags & NLM_F_ACK ? 'A' : '-',
|
||||
nlh->nlmsg_flags & NLM_F_ECHO ? 'E' : '-');
|
||||
fprintf(fd, "| %.010u |\t| sequence number|\n", nlh->nlmsg_seq);
|
||||
fprintf(fd, "| %.010u |\t| port ID |\n", nlh->nlmsg_pid);
|
||||
fprintf(fd, "----------------\t------------------\n");
|
||||
}
|
||||
|
||||
static void mnl_nlmsg_fprintf_payload(FILE *fd, const struct nlmsghdr *nlh,
|
||||
size_t extra_header_size)
|
||||
{
|
||||
int rem = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i=sizeof(struct nlmsghdr); i<nlh->nlmsg_len; i+=4) {
|
||||
char *b = (char *) nlh;
|
||||
struct nlattr *attr = (struct nlattr *) (b+i);
|
||||
|
||||
/* netlink control message. */
|
||||
if (nlh->nlmsg_type < NLMSG_MIN_TYPE) {
|
||||
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||
0xff & b[i], 0xff & b[i+1],
|
||||
0xff & b[i+2], 0xff & b[i+3]);
|
||||
fprintf(fd, "| |\n");
|
||||
/* special handling for the extra header. */
|
||||
} else if (extra_header_size > 0) {
|
||||
extra_header_size -= 4;
|
||||
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||
0xff & b[i], 0xff & b[i+1],
|
||||
0xff & b[i+2], 0xff & b[i+3]);
|
||||
fprintf(fd, "| extra header |\n");
|
||||
/* this seems like an attribute header. */
|
||||
} else if (rem == 0 && (attr->nla_type & NLA_TYPE_MASK) != 0) {
|
||||
fprintf(fd, "|%c[%d;%dm"
|
||||
"%.5u"
|
||||
"%c[%dm"
|
||||
"|"
|
||||
"%c[%d;%dm"
|
||||
"%c%c"
|
||||
"%c[%dm"
|
||||
"|"
|
||||
"%c[%d;%dm"
|
||||
"%.5u"
|
||||
"%c[%dm|\t",
|
||||
27, 1, 31,
|
||||
attr->nla_len,
|
||||
27, 0,
|
||||
27, 1, 32,
|
||||
attr->nla_type & NLA_F_NESTED ? 'N' : '-',
|
||||
attr->nla_type &
|
||||
NLA_F_NET_BYTEORDER ? 'B' : '-',
|
||||
27, 0,
|
||||
27, 1, 34,
|
||||
attr->nla_type & NLA_TYPE_MASK,
|
||||
27, 0);
|
||||
fprintf(fd, "|len |flags| type|\n");
|
||||
|
||||
if (!(attr->nla_type & NLA_F_NESTED)) {
|
||||
rem = NLA_ALIGN(attr->nla_len) -
|
||||
sizeof(struct nlattr);
|
||||
}
|
||||
/* this is the attribute payload. */
|
||||
} else if (rem > 0) {
|
||||
rem -= 4;
|
||||
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||
0xff & b[i], 0xff & b[i+1],
|
||||
0xff & b[i+2], 0xff & b[i+3]);
|
||||
fprintf(fd, "| data |");
|
||||
fprintf(fd, "\t %c %c %c %c\n",
|
||||
isprint(b[i]) ? b[i] : ' ',
|
||||
isprint(b[i+1]) ? b[i+1] : ' ',
|
||||
isprint(b[i+2]) ? b[i+2] : ' ',
|
||||
isprint(b[i+3]) ? b[i+3] : ' ');
|
||||
}
|
||||
}
|
||||
fprintf(fd, "----------------\t------------------\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_fprintf - print netlink message to file
|
||||
* \param fd pointer to file type
|
||||
* \param data pointer to the buffer that contains messages to be printed
|
||||
* \param datalen length of data stored in the buffer
|
||||
* \param extra_header_size size of the extra header (if any)
|
||||
*
|
||||
* This function prints the netlink header to a file handle.
|
||||
* It may be useful for debugging purposes. One example of the output
|
||||
* is the following:
|
||||
*
|
||||
*\verbatim
|
||||
---------------- ------------------
|
||||
| 0000000040 | | message length |
|
||||
| 00016 | R-A- | | type | flags |
|
||||
| 1289148991 | | sequence number|
|
||||
| 0000000000 | | port ID |
|
||||
---------------- ------------------
|
||||
| 00 00 00 00 | | extra header |
|
||||
| 00 00 00 00 | | extra header |
|
||||
| 01 00 00 00 | | extra header |
|
||||
| 01 00 00 00 | | extra header |
|
||||
|00008|--|00003| |len |flags| type|
|
||||
| 65 74 68 30 | | data | e t h 0
|
||||
---------------- ------------------
|
||||
\endverbatim
|
||||
*
|
||||
* This example above shows the netlink message that is send to kernel-space
|
||||
* to set up the link interface eth0. The netlink and attribute header data
|
||||
* are displayed in base 10 whereas the extra header and the attribute payload
|
||||
* are expressed in base 16. The possible flags in the netlink header are:
|
||||
*
|
||||
* - R, that indicates that NLM_F_REQUEST is set.
|
||||
* - M, that indicates that NLM_F_MULTI is set.
|
||||
* - A, that indicates that NLM_F_ACK is set.
|
||||
* - E, that indicates that NLM_F_ECHO is set.
|
||||
*
|
||||
* The lack of one flag is displayed with '-'. On the other hand, the possible
|
||||
* attribute flags available are:
|
||||
*
|
||||
* - N, that indicates that NLA_F_NESTED is set.
|
||||
* - B, that indicates that NLA_F_NET_BYTEORDER is set.
|
||||
*/
|
||||
void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen,
|
||||
size_t extra_header_size)
|
||||
{
|
||||
const struct nlmsghdr *nlh = data;
|
||||
int len = datalen;
|
||||
|
||||
while (mnl_nlmsg_ok(nlh, len)) {
|
||||
mnl_nlmsg_fprintf_header(fd, nlh);
|
||||
mnl_nlmsg_fprintf_payload(fd, nlh, extra_header_size);
|
||||
nlh = mnl_nlmsg_next(nlh, &len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup batch Netlink message batch helpers
|
||||
*
|
||||
* This library provides helpers to batch several messages into one single
|
||||
* datagram. These helpers do not perform strict memory boundary checkings.
|
||||
*
|
||||
* The following figure represents a Netlink message batch:
|
||||
*
|
||||
* |<-------------- MNL_SOCKET_BUFFER_SIZE ------------->|
|
||||
* |<-------------------- batch ------------------>| |
|
||||
* |-----------|-----------|-----------|-----------|-----------|
|
||||
* |<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|
|
||||
* |-----------|-----------|-----------|-----------|-----------|
|
||||
* ^ ^
|
||||
* | |
|
||||
* message N message N+1
|
||||
*
|
||||
* To start the batch, you have to call mnl_nlmsg_batch_start() and you can
|
||||
* use mnl_nlmsg_batch_stop() to release it.
|
||||
*
|
||||
* You have to invoke mnl_nlmsg_batch_next() to get room for a new message
|
||||
* in the batch. If this function returns NULL, it means that the last
|
||||
* message that was added (message N+1 in the figure above) does not fit the
|
||||
* batch. Thus, you have to send the batch (which includes until message N)
|
||||
* and, then, you have to call mnl_nlmsg_batch_reset() to re-initialize
|
||||
* the batch (this moves message N+1 to the head of the buffer). For that
|
||||
* reason, the buffer that you have to use to store the batch must be double
|
||||
* of MNL_SOCKET_BUFFER_SIZE to ensure that the last message (message N+1)
|
||||
* that did not fit into the batch is written inside valid memory boundaries.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct mnl_nlmsg_batch {
|
||||
/* the buffer that is used to store the batch. */
|
||||
void *buf;
|
||||
size_t limit;
|
||||
size_t buflen;
|
||||
/* the current netlink message in the batch. */
|
||||
void *cur;
|
||||
bool overflow;
|
||||
};
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_start - initialize a batch
|
||||
* \param buf pointer to the buffer that will store this batch
|
||||
* \param limit maximum size of the batch (should be MNL_SOCKET_BUFFER_SIZE).
|
||||
*
|
||||
* The buffer that you pass must be double of MNL_SOCKET_BUFFER_SIZE. The
|
||||
* limit must be half of the buffer size, otherwise expect funny memory
|
||||
* corruptions 8-).
|
||||
*
|
||||
* You can allocate the buffer that you use to store the batch in the stack or
|
||||
* the heap, no restrictions in this regard. This function returns NULL on
|
||||
* error.
|
||||
*/
|
||||
struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf,
|
||||
size_t limit)
|
||||
{
|
||||
struct mnl_nlmsg_batch *b;
|
||||
|
||||
b = malloc(sizeof(struct mnl_nlmsg_batch));
|
||||
if (b == NULL)
|
||||
return NULL;
|
||||
|
||||
b->buf = buf;
|
||||
b->limit = limit;
|
||||
b->buflen = 0;
|
||||
b->cur = buf;
|
||||
b->overflow = false;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_stop - release a batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function releases the batch allocated by mnl_nlmsg_batch_start().
|
||||
*/
|
||||
void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
free(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_next - get room for the next message in the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns false if the last message did not fit into the
|
||||
* batch. Otherwise, it prepares the batch to provide room for the new
|
||||
* Netlink message in the batch and returns true.
|
||||
*
|
||||
* You have to put at least one message in the batch before calling this
|
||||
* function, otherwise your application is likely to crash.
|
||||
*/
|
||||
bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
struct nlmsghdr *nlh = b->cur;
|
||||
|
||||
if (b->buflen + nlh->nlmsg_len > b->limit) {
|
||||
b->overflow = true;
|
||||
return false;
|
||||
}
|
||||
b->cur = b->buf + b->buflen + nlh->nlmsg_len;
|
||||
b->buflen += nlh->nlmsg_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_reset - reset the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function allows to reset a batch, so you can reuse it to create a
|
||||
* new one. This function moves the last message which does not fit the
|
||||
* batch to the head of the buffer, if any.
|
||||
*/
|
||||
void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
if (b->overflow) {
|
||||
struct nlmsghdr *nlh = b->cur;
|
||||
memcpy(b->buf, b->cur, nlh->nlmsg_len);
|
||||
b->buflen = nlh->nlmsg_len;
|
||||
b->cur = b->buf + b->buflen;
|
||||
b->overflow = false;
|
||||
} else {
|
||||
b->buflen = 0;
|
||||
b->cur = b->buf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_size - get current size of the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns the current size of the batch.
|
||||
*/
|
||||
size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->buflen;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_head - get head of this batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns a pointer to the head of the batch, which is the
|
||||
* beginning of the buffer that is used.
|
||||
*/
|
||||
void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_current - returns current position in the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns a pointer to the current position in the buffer
|
||||
* that is used to store the batch.
|
||||
*/
|
||||
void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_is_empty - check if there is any message in the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns true if the batch is empty.
|
||||
*/
|
||||
bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->buflen == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@ -1,351 +0,0 @@
|
||||
/*
|
||||
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
|
||||
/**
|
||||
* \mainpage
|
||||
*
|
||||
* libmnl is a minimalistic user-space library oriented to Netlink developers.
|
||||
* There are a lot of common tasks in parsing, validating, constructing of
|
||||
* both the Netlink header and TLVs that are repetitive and easy to get wrong.
|
||||
* This library aims to provide simple helpers that allows you to avoid
|
||||
* re-inventing the wheel in common Netlink tasks.
|
||||
*
|
||||
* \verbatim
|
||||
"Simplify, simplify" -- Henry David Thoureau. Walden (1854)
|
||||
\endverbatim
|
||||
*
|
||||
* The acronym libmnl stands for LIBrary Minimalistic NetLink.
|
||||
*
|
||||
* libmnl homepage is:
|
||||
* http://www.netfilter.org/projects/libmnl/
|
||||
*
|
||||
* \section features Main Features
|
||||
* - Small: the shared library requires around 30KB for an x86-based computer.
|
||||
* - Simple: this library avoids complex abstractions that tend to hide Netlink
|
||||
* details. It avoids elaborated object-oriented infrastructure and complex
|
||||
* callback-based workflow.
|
||||
* - Easy to use: the library simplifies the work for Netlink-wise developers.
|
||||
* It provides functions to make socket handling, message building,
|
||||
* validating, parsing and sequence tracking, easier.
|
||||
* - Easy to re-use: you can use this library to build your own abstraction
|
||||
* layer upon this library, if you want to provide another library that
|
||||
* hides Netlink details to your users.
|
||||
* - Decoupling: the interdependency of the main bricks that compose this
|
||||
* library is reduced, i.e. the library provides many helpers, but the
|
||||
* programmer is not forced to use them.
|
||||
*
|
||||
* \section licensing Licensing terms
|
||||
* This library is released under the LGPLv2.1 or any later (at your option).
|
||||
*
|
||||
* \section Dependencies
|
||||
* You have to install the Linux kernel headers that you want to use to develop
|
||||
* your application. Moreover, this library requires that you have some basics
|
||||
* on Netlink.
|
||||
*
|
||||
* \section scm Git Tree
|
||||
* The current development version of libmnl can be accessed at:
|
||||
* http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libmnl.git;a=summary
|
||||
*
|
||||
* \section using Using libmnl
|
||||
* You can access several example files under examples/ in the libmnl source
|
||||
* code tree.
|
||||
*/
|
||||
|
||||
struct mnl_socket {
|
||||
int fd;
|
||||
struct sockaddr_nl addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* \defgroup socket Netlink socket helpers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* mnl_socket_get_fd - obtain file descriptor from netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
*
|
||||
* This function returns the file descriptor of a given netlink socket.
|
||||
*/
|
||||
int mnl_socket_get_fd(const struct mnl_socket *nl)
|
||||
{
|
||||
return nl->fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_get_portid - obtain Netlink PortID from netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
*
|
||||
* This function returns the Netlink PortID of a given netlink socket.
|
||||
* It's a common mistake to assume that this PortID equals the process ID
|
||||
* which is not always true. This is the case if you open more than one
|
||||
* socket that is binded to the same Netlink subsystem from the same process.
|
||||
*/
|
||||
unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
|
||||
{
|
||||
return nl->addr.nl_pid;
|
||||
}
|
||||
|
||||
static struct mnl_socket *__mnl_socket_open(int bus, int flags)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
|
||||
nl = calloc(1, sizeof(struct mnl_socket));
|
||||
if (nl == NULL)
|
||||
return NULL;
|
||||
|
||||
nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
|
||||
if (nl->fd == -1) {
|
||||
free(nl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_open - open a netlink socket
|
||||
* \param bus the netlink socket bus ID (see NETLINK_* constants)
|
||||
*
|
||||
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||
* returns a valid pointer to the mnl_socket structure.
|
||||
*/
|
||||
struct mnl_socket *mnl_socket_open(int bus)
|
||||
{
|
||||
return __mnl_socket_open(bus, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_open2 - open a netlink socket with appropriate flags
|
||||
* \param bus the netlink socket bus ID (see NETLINK_* constants)
|
||||
* \param flags the netlink socket flags (see SOCK_* constants in socket(2))
|
||||
*
|
||||
* This is similar to mnl_socket_open(), but allows to set flags like
|
||||
* SOCK_CLOEXEC at socket creation time (useful for multi-threaded programs
|
||||
* performing exec calls).
|
||||
*
|
||||
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||
* returns a valid pointer to the mnl_socket structure.
|
||||
*/
|
||||
struct mnl_socket *mnl_socket_open2(int bus, int flags)
|
||||
{
|
||||
return __mnl_socket_open(bus, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_fdopen - associates a mnl_socket object with pre-existing socket.
|
||||
* \param fd pre-existing socket descriptor.
|
||||
*
|
||||
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||
* returns a valid pointer to the mnl_socket structure. It also sets the portID
|
||||
* if the socket fd is already bound and it is AF_NETLINK.
|
||||
*
|
||||
* Note that mnl_socket_get_portid() returns 0 if this function is used with
|
||||
* non-netlink socket.
|
||||
*/
|
||||
struct mnl_socket *mnl_socket_fdopen(int fd)
|
||||
{
|
||||
int ret;
|
||||
struct mnl_socket *nl;
|
||||
struct sockaddr_nl addr;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_nl);
|
||||
|
||||
ret = getsockname(fd, (struct sockaddr *) &addr, &addr_len);
|
||||
if (ret == -1)
|
||||
return NULL;
|
||||
|
||||
nl = calloc(1, sizeof(struct mnl_socket));
|
||||
if (nl == NULL)
|
||||
return NULL;
|
||||
|
||||
nl->fd = fd;
|
||||
if (addr.nl_family == AF_NETLINK)
|
||||
nl->addr = addr;
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_bind - bind netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param groups the group of message you're interested in
|
||||
* \param pid the port ID you want to use (use zero for automatic selection)
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set. On
|
||||
* success, 0 is returned. You can use MNL_SOCKET_AUTOPID which is 0 for
|
||||
* automatic port ID selection.
|
||||
*/
|
||||
int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups,
|
||||
pid_t pid)
|
||||
{
|
||||
int ret;
|
||||
socklen_t addr_len;
|
||||
|
||||
nl->addr.nl_family = AF_NETLINK;
|
||||
nl->addr.nl_groups = groups;
|
||||
nl->addr.nl_pid = pid;
|
||||
|
||||
ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
addr_len = sizeof(nl->addr);
|
||||
ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (addr_len != sizeof(nl->addr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (nl->addr.nl_family != AF_NETLINK) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_sendto - send a netlink message of a certain size
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param buf buffer containing the netlink message to be sent
|
||||
* \param len number of bytes in the buffer that you want to send
|
||||
*
|
||||
* On error, it returns -1 and errno is appropriately set. Otherwise, it
|
||||
* returns the number of bytes sent.
|
||||
*/
|
||||
ssize_t mnl_socket_sendto(const struct mnl_socket *nl,
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
static const struct sockaddr_nl snl = {
|
||||
.nl_family = AF_NETLINK
|
||||
};
|
||||
return sendto(nl->fd, buf, len, 0,
|
||||
(struct sockaddr *) &snl, sizeof(snl));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_recvfrom - receive a netlink message
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param buf buffer that you want to use to store the netlink message
|
||||
* \param bufsiz size of the buffer passed to store the netlink message
|
||||
*
|
||||
* On error, it returns -1 and errno is appropriately set. If errno is set
|
||||
* to ENOSPC, it means that the buffer that you have passed to store the
|
||||
* netlink message is too small, so you have received a truncated message.
|
||||
* To avoid this, you have to allocate a buffer of MNL_SOCKET_BUFFER_SIZE
|
||||
* (which is 8KB, see linux/netlink.h for more information). Using this
|
||||
* buffer size ensures that your buffer is big enough to store the netlink
|
||||
* message without truncating it.
|
||||
*/
|
||||
ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl,
|
||||
void *buf, size_t bufsiz)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct sockaddr_nl addr;
|
||||
struct iovec iov = {
|
||||
.iov_base = buf,
|
||||
.iov_len = bufsiz,
|
||||
};
|
||||
struct msghdr msg = {
|
||||
.msg_name = &addr,
|
||||
.msg_namelen = sizeof(struct sockaddr_nl),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = NULL,
|
||||
.msg_controllen = 0,
|
||||
.msg_flags = 0,
|
||||
};
|
||||
ret = recvmsg(nl->fd, &msg, 0);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_close - close a given netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set.
|
||||
* On success, it returns 0.
|
||||
*/
|
||||
int mnl_socket_close(struct mnl_socket *nl)
|
||||
{
|
||||
int ret = close(nl->fd);
|
||||
free(nl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_setsockopt - set Netlink socket option
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param type type of Netlink socket options
|
||||
* \param buf the buffer that contains the data about this option
|
||||
* \param len the size of the buffer passed
|
||||
*
|
||||
* This function allows you to set some Netlink socket option. As of writing
|
||||
* this (see linux/netlink.h), the existing options are:
|
||||
*
|
||||
* - \#define NETLINK_ADD_MEMBERSHIP 1
|
||||
* - \#define NETLINK_DROP_MEMBERSHIP 2
|
||||
* - \#define NETLINK_PKTINFO 3
|
||||
* - \#define NETLINK_BROADCAST_ERROR 4
|
||||
* - \#define NETLINK_NO_ENOBUFS 5
|
||||
*
|
||||
* In the early days, Netlink only supported 32 groups expressed in a
|
||||
* 32-bits mask. However, since 2.6.14, Netlink may have up to 2^32 multicast
|
||||
* groups but you have to use setsockopt() with NETLINK_ADD_MEMBERSHIP to
|
||||
* join a given multicast group. This function internally calls setsockopt()
|
||||
* to join a given netlink multicast group. You can still use mnl_bind()
|
||||
* and the 32-bit mask to join a set of Netlink multicast groups.
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set.
|
||||
*/
|
||||
int mnl_socket_setsockopt(const struct mnl_socket *nl, int type,
|
||||
void *buf, socklen_t len)
|
||||
{
|
||||
return setsockopt(nl->fd, SOL_NETLINK, type, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_getsockopt - get a Netlink socket option
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param type type of Netlink socket options
|
||||
* \param buf pointer to the buffer to store the value of this option
|
||||
* \param len size of the information written in the buffer
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set.
|
||||
*/
|
||||
int mnl_socket_getsockopt(const struct mnl_socket *nl, int type,
|
||||
void *buf, socklen_t *len)
|
||||
{
|
||||
return getsockopt(nl->fd, SOL_NETLINK, type, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,67 +0,0 @@
|
||||
[Setting]
|
||||
qmap_num=4
|
||||
|
||||
[profile1]
|
||||
apn=1234567890
|
||||
user=qwertyuio
|
||||
password=asdfghjkl
|
||||
auth=2
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile2]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=0
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile3]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=0
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile4]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=0
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile5]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile6]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile7]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile8]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
@ -1,438 +0,0 @@
|
||||
#include "QMIThread.h"
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
#include <net/if.h>
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
|
||||
static size_t fibo_fread(const char *filename, void *buf, size_t size)
|
||||
{
|
||||
FILE *fp = fopen(filename, "r");
|
||||
size_t n = 0;
|
||||
|
||||
memset(buf, 0x00, size);
|
||||
|
||||
if (fp) {
|
||||
n = fread(buf, 1, size, fp);
|
||||
if (n <= 0 || n == size) {
|
||||
dbg_time(
|
||||
"warnning: fail to fread(%s), fread=%zd, buf_size=%zd, "
|
||||
"errno: %d (%s)",
|
||||
__func__, filename, n, size, errno, strerror(errno));
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return n > 0 ? n : 0;
|
||||
}
|
||||
|
||||
static size_t fibo_fwrite(const char *filename, const void *buf, size_t size)
|
||||
{
|
||||
FILE *fp = fopen(filename, "w");
|
||||
size_t n = 0;
|
||||
|
||||
if (fp) {
|
||||
n = fwrite(buf, 1, size, fp);
|
||||
if (n != size) {
|
||||
dbg_time(
|
||||
"warnning: fail to fwrite(%s), fwrite=%zd, buf_size=%zd, "
|
||||
"errno: %d (%s)",
|
||||
__func__, filename, n, size, errno, strerror(errno));
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return n > 0 ? n : 0;
|
||||
}
|
||||
|
||||
static int fibo_iface_is_in_bridge(const char *iface)
|
||||
{
|
||||
char filename[256];
|
||||
|
||||
snprintf(filename, sizeof(filename), "/sys/class/net/%s/brport", iface);
|
||||
return (access(filename, F_OK) == 0 || errno != ENOENT);
|
||||
}
|
||||
|
||||
int fibo_bridge_mode_detect(PROFILE_T *profile)
|
||||
{
|
||||
const char *ifname = profile->qmapnet_adapter ? profile->qmapnet_adapter
|
||||
: profile->usbnet_adapter;
|
||||
const char *driver;
|
||||
char bridge_mode[128];
|
||||
char bridge_ipv4[128];
|
||||
char ipv4[128];
|
||||
char buf[64];
|
||||
size_t n;
|
||||
int in_bridge;
|
||||
|
||||
driver = profile->driver_name;
|
||||
snprintf(bridge_mode, sizeof(bridge_mode), "/sys/class/net/%s/bridge_mode",
|
||||
ifname);
|
||||
snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/class/net/%s/bridge_ipv4",
|
||||
ifname);
|
||||
|
||||
if (access(bridge_mode, F_OK) && errno == ENOENT) {
|
||||
snprintf(bridge_mode, sizeof(bridge_mode),
|
||||
"/sys/module/%s/parameters/bridge_mode", driver);
|
||||
snprintf(bridge_ipv4, sizeof(bridge_ipv4),
|
||||
"/sys/module/%s/parameters/bridge_ipv4", driver);
|
||||
|
||||
if (access(bridge_mode, F_OK) && errno == ENOENT) {
|
||||
bridge_mode[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
in_bridge = fibo_iface_is_in_bridge(ifname);
|
||||
if (in_bridge) {
|
||||
dbg_time("notice: iface %s had add to bridge\n", ifname);
|
||||
}
|
||||
|
||||
if (in_bridge && bridge_mode[0] == '\0') {
|
||||
dbg_time("warnning: can not find bride_mode file for %s\n", ifname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = fibo_fread(bridge_mode, buf, sizeof(buf));
|
||||
|
||||
if (in_bridge) {
|
||||
if (n <= 0 || buf[0] == '0') {
|
||||
dbg_time("warnning: should set 1 to bride_mode file for %s\n",
|
||||
ifname);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (n <= 0 || buf[0] == '0') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memset(ipv4, 0, sizeof(ipv4));
|
||||
|
||||
if (strstr(bridge_ipv4, "/sys/class/net/") || profile->qmap_mode == 0 ||
|
||||
profile->qmap_mode == 1) {
|
||||
snprintf(ipv4, sizeof(ipv4), "0x%x", profile->ipv4.Address);
|
||||
dbg_time("echo '%s' > %s", ipv4, bridge_ipv4);
|
||||
fibo_fwrite(bridge_ipv4, ipv4, strlen(ipv4));
|
||||
} else {
|
||||
snprintf(ipv4, sizeof(ipv4), "0x%x:%d", profile->ipv4.Address,
|
||||
profile->muxid);
|
||||
dbg_time("echo '%s' > %s", ipv4, bridge_ipv4);
|
||||
fibo_fwrite(bridge_ipv4, ipv4, strlen(ipv4));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
void fibo_get_driver_info(PROFILE_T *profile, RMNET_INFO *rmnet_info) {
|
||||
int ifc_ctl_sock;
|
||||
struct ifreq ifr;
|
||||
int rc;
|
||||
int request = 0x89F3;
|
||||
unsigned char data[512];
|
||||
|
||||
memset(rmnet_info, 0x00, sizeof(*rmnet_info));
|
||||
|
||||
ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (ifc_ctl_sock <= 0) {
|
||||
dbg_time("socket() failed: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&ifr, 0, sizeof(struct ifreq));
|
||||
strncpy(ifr.ifr_name, profile->usbnet_adapter, IFNAMSIZ);
|
||||
ifr.ifr_name[IFNAMSIZ - 1] = 0;
|
||||
ifr.ifr_ifru.ifru_data = (void *)data;
|
||||
rc = ioctl(ifc_ctl_sock, request, &ifr);
|
||||
if (rc < 0) {
|
||||
dbg_time("ioctl(0x%x, qmap_settings) failed: %s, rc=%d", request, strerror(errno), rc);
|
||||
}
|
||||
else {
|
||||
memcpy(rmnet_info, data, sizeof(*rmnet_info));
|
||||
}
|
||||
|
||||
close(ifc_ctl_sock);
|
||||
}
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
int fibo_qmap_mode_detect(PROFILE_T *profile)
|
||||
{
|
||||
int n;
|
||||
char buf[128];
|
||||
char qmap_netcard[128];
|
||||
struct {
|
||||
char filename[255 * 2];
|
||||
char linkname[255 * 2];
|
||||
} * pl;
|
||||
|
||||
pl = (typeof(pl))malloc(sizeof(*pl));
|
||||
|
||||
snprintf(pl->linkname, sizeof(pl->linkname),
|
||||
"/sys/class/net/%s/device/driver", profile->usbnet_adapter);
|
||||
n = readlink(pl->linkname, pl->filename, sizeof(pl->filename));
|
||||
pl->filename[n] = '\0';
|
||||
while (pl->filename[n] != '/') n--;
|
||||
profile->driver_name = strdup(&pl->filename[n + 1]);
|
||||
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
fibo_get_driver_info(profile, &profile->rmnet_info);
|
||||
if (profile->rmnet_info.size) {
|
||||
profile->qmap_mode = profile->rmnet_info.qmap_mode;
|
||||
if (profile->qmap_mode) {
|
||||
int offset_id = profile->pdp - 1;
|
||||
|
||||
if (profile->qmap_mode == 1)
|
||||
offset_id = 0;
|
||||
profile->muxid = profile->rmnet_info.mux_id[offset_id];
|
||||
profile->qmapnet_adapter = strdup( profile->rmnet_info.ifname[offset_id]);
|
||||
profile->qmap_size = profile->rmnet_info.rx_urb_size;
|
||||
profile->qmap_version = profile->rmnet_info.qmap_version;
|
||||
}
|
||||
|
||||
goto _out;
|
||||
}
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
|
||||
if (qmidev_is_pciemhi(profile->qmichannel)) {
|
||||
profile->qmap_mode = 1;
|
||||
|
||||
if (profile->muxid == 0 || profile->muxid == 0x81)
|
||||
{
|
||||
profile->muxid = 0x81;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (profile->muxid < 0x80)
|
||||
profile->muxid += 0x81;
|
||||
profile->qmap_mode = 2;
|
||||
}
|
||||
|
||||
profile->qmapnet_adapter = strdup(profile->usbnet_adapter);
|
||||
goto _final_process;
|
||||
}
|
||||
|
||||
snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_num",
|
||||
profile->usbnet_adapter);
|
||||
|
||||
//2021-01-27 willa.liu@fibocom.com changed begin for support mantis 0068849
|
||||
if (access(pl->filename, F_OK) == 0) {
|
||||
dbg_time("access %s", pl->filename);
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno,
|
||||
strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837
|
||||
/*
|
||||
snprintf(pl->filename, sizeof(pl->filename),
|
||||
"/sys/module/%s/parameters/qmap_num", profile->driver_name);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
|
||||
snprintf(
|
||||
pl->filename, sizeof(pl->filename),
|
||||
"/sys/class/net/%s/device/driver/module/parameters/qmap_num",
|
||||
profile->usbnet_adapter);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
//2021-02-01 willa.liu@fibocom.com changed end for support mantis 0069837
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_mode",
|
||||
profile->usbnet_adapter);
|
||||
|
||||
if (access(pl->filename, F_OK) == 0) {
|
||||
dbg_time("access %s", pl->filename);
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno,
|
||||
strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!access(pl->filename, R_OK))
|
||||
{
|
||||
n = fibo_fread(pl->filename, buf, sizeof(buf));
|
||||
if(n > 0)
|
||||
{
|
||||
profile->qmap_mode = atoi(buf);
|
||||
if(profile->qmap_mode >= 1 && qmidev_is_pciemhi(profile->qmichannel))
|
||||
{
|
||||
profile->muxid =
|
||||
profile->pdp + 0x80;
|
||||
sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
if(qmidev_is_gobinet(profile->qmichannel) || qmidev_is_qmiwwan(profile->qmichannel))
|
||||
{
|
||||
if(profile->qmap_mode > 1)
|
||||
{
|
||||
profile->muxid =
|
||||
profile->pdp + 0x80;
|
||||
sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
if(profile->qmap_mode == 1)
|
||||
{
|
||||
profile->muxid = 0x81;
|
||||
profile->qmapnet_adapter = strdup(profile->usbnet_adapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (0) {
|
||||
profile->qmap_mode = atoi(buf);
|
||||
|
||||
if (profile->qmap_mode > 1 && qmidev_is_gobinet(profile->qmichannel)) {
|
||||
profile->muxid =
|
||||
profile->pdp + 0x80; // muxis is 0x8X for PDN-X
|
||||
sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
if (profile->qmap_mode >= 1 && !qmidev_is_gobinet(profile->qmichannel)) {
|
||||
profile->muxid =
|
||||
profile->pdp + 0x80; // muxis is 0x8X for PDN-X
|
||||
sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
if (profile->qmap_mode == 1 && qmidev_is_gobinet(profile->qmichannel)) {
|
||||
profile->muxid = 0x81;
|
||||
profile->qmapnet_adapter = strdup(profile->usbnet_adapter);
|
||||
//2021-01-27 willa.liu@fibocom.com changed end for support mantis 0068849
|
||||
|
||||
}
|
||||
}
|
||||
} else if (qmidev_is_qmiwwan(profile->qmichannel)) {
|
||||
snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/qmimux%d",
|
||||
profile->pdp - 1);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
}
|
||||
goto _out;
|
||||
}
|
||||
|
||||
// upstream Kernel Style QMAP qmi_wwan.c
|
||||
snprintf(pl->filename, sizeof(pl->filename),
|
||||
"/sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter);
|
||||
n = fibo_fread(pl->filename, buf, sizeof(buf));
|
||||
if (n >= 5) {
|
||||
profile->qmap_mode = n / 5; // 0x81\n0x82\n0x83\n
|
||||
if (profile->qmap_mode > 1) {
|
||||
// PDN-X map to qmimux-X
|
||||
profile->muxid = (buf[5 * (profile->pdp - 1) + 2] - '0') * 16 +
|
||||
(buf[5 * (profile->pdp - 1) + 3] - '0');
|
||||
sprintf(qmap_netcard, "qmimux%d", profile->pdp - 1);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
} else if (profile->qmap_mode == 1) {
|
||||
profile->muxid =
|
||||
(buf[5 * 0 + 2] - '0') * 16 + (buf[5 * 0 + 3] - '0');
|
||||
sprintf(qmap_netcard, "qmimux%d", 0);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_out:
|
||||
if (profile->qmap_mode) {
|
||||
profile->qmap_size = 16 * 1024;
|
||||
snprintf(pl->filename, sizeof(pl->filename),
|
||||
"/sys/class/net/%s/qmap_size", profile->usbnet_adapter);
|
||||
if (!access(pl->filename, R_OK)) {
|
||||
size_t n;
|
||||
char buf[32];
|
||||
n = fibo_fread(pl->filename, buf, sizeof(buf));
|
||||
if (n > 0) {
|
||||
profile->qmap_size = atoi(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_final_process:
|
||||
if (profile->qmap_mode)
|
||||
dbg_time("qmap_mode = %d, muxid = 0x%02x, qmap_netcard = %s",
|
||||
profile->qmap_mode, profile->muxid, profile->qmapnet_adapter);
|
||||
|
||||
free(pl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fibo_qmap_mode_set(PROFILE_T *profile)
|
||||
{
|
||||
int n;
|
||||
char buf[128];
|
||||
struct {
|
||||
char filename[255 * 2];
|
||||
char linkname[255 * 2];
|
||||
} * pl;
|
||||
|
||||
if (qmidev_is_pciemhi(profile->qmichannel))
|
||||
{
|
||||
dbg_time("pcie mode exit fibo_qmap_mode_set ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pl = (typeof(pl))malloc(sizeof(*pl));
|
||||
|
||||
snprintf(pl->linkname, sizeof(pl->linkname),
|
||||
"/sys/class/net/%s/device/driver", profile->usbnet_adapter);
|
||||
n = readlink(pl->linkname, pl->filename, sizeof(pl->filename));
|
||||
pl->filename[n] = '\0';
|
||||
while (pl->filename[n] != '/') n--;
|
||||
profile->driver_name = strdup(&pl->filename[n + 1]);
|
||||
|
||||
snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_num",
|
||||
profile->usbnet_adapter);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno,
|
||||
strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
|
||||
snprintf(pl->filename, sizeof(pl->filename),
|
||||
"/sys/module/%s/parameters/qmap_mnum", profile->driver_name);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
|
||||
snprintf(
|
||||
pl->filename, sizeof(pl->filename),
|
||||
"/sys/class/net/%s/device/driver/module/parameters/qmap_num",
|
||||
profile->usbnet_adapter);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!access(pl->filename, R_OK)) {
|
||||
snprintf(buf, sizeof(buf), "%d", profile->pdpnum);
|
||||
n = fibo_fwrite(pl->filename, buf, strlen(buf));
|
||||
}
|
||||
|
||||
_out:
|
||||
|
||||
free(pl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,160 +0,0 @@
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
#include "QMIThread.h"
|
||||
#include "query_pcie_mode.h"
|
||||
int speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300,//
|
||||
B38400, B19200, B9600, B4800, B2400, B1200, B300,
|
||||
};
|
||||
int name_arr[] = {115200, 19200, 9600, 4800, 2400, 1200, 300,
|
||||
38400, 19200, 9600, 4800, 2400, 1200, 300,
|
||||
};
|
||||
|
||||
int get_pcie_mode_debug = 0;
|
||||
|
||||
//2021-02-24 willa.liu@fibocom.com changed begin for support eipd SN-20210129001
|
||||
int get_private_gateway_debug = 1;
|
||||
//2021-02-24 willa.liu@fibocom.com changed end for support eipd SN-20210129001
|
||||
|
||||
//static int xset1(int fd, struct termios *tio, const char *device)
|
||||
int xset1(int fd, struct termios *tio, const char *device)
|
||||
{
|
||||
int ret = tcsetattr(fd, TCSAFLUSH, tio);
|
||||
|
||||
if (ret) {
|
||||
printf("can't tcsetattr for %s", device);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// set raw tty mode
|
||||
//static void xget1(int fd, struct termios *t, struct termios *oldt)
|
||||
void xget1(int fd, struct termios *t, struct termios *oldt)
|
||||
{
|
||||
tcgetattr(fd, oldt);
|
||||
*t = *oldt;
|
||||
cfmakeraw(t);
|
||||
// t->c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
|
||||
// t->c_iflag &= ~(BRKINT|IXON|ICRNL);
|
||||
// t->c_oflag &= ~(ONLCR);
|
||||
// t->c_cc[VMIN] = 1;
|
||||
// t->c_cc[VTIME] = 0;
|
||||
}
|
||||
|
||||
//static int get_pcie_mode()
|
||||
int get_pcie_mode()
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
{
|
||||
int i;
|
||||
int fd;
|
||||
int ret;
|
||||
char buffer[409600] = {0};
|
||||
int rate;
|
||||
char* sendbuffer;
|
||||
int totallen = 0;
|
||||
fd_set readfds;
|
||||
struct timeval timeout;
|
||||
struct termios tio0, tiosfd, tio;
|
||||
|
||||
int timeoutVal = 5;
|
||||
|
||||
char *dev = "/dev/ttyUSB1"; //The port under Linux is operated by opening the device file
|
||||
rate = 115200;
|
||||
sendbuffer = "at+gtpcie=3";
|
||||
printf ( "dev: %s\nrate:%d\nsendbuffer:%s\n", dev,rate,sendbuffer);
|
||||
|
||||
fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
goto ERR;
|
||||
fcntl(fd, F_SETFL, O_RDWR);
|
||||
|
||||
// put device to "raw mode"
|
||||
xget1(fd, &tio, &tiosfd);
|
||||
// set device speed
|
||||
for ( i = 0;i < sizeof ( speed_arr ) / sizeof ( int );i++ )
|
||||
{
|
||||
if ( rate == name_arr[i] ) //Judge if the pass is equal to the pass
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i >= sizeof ( speed_arr ) / sizeof ( int ))
|
||||
{
|
||||
printf("bound rate set failed\n");
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
cfsetspeed(&tio, speed_arr[i]);
|
||||
if (xset1(fd, &tio, dev))
|
||||
goto ERR;
|
||||
|
||||
tcflush ( fd, TCIOFLUSH );
|
||||
|
||||
sprintf(buffer, "%s\r", sendbuffer);
|
||||
ret = write ( fd, buffer, strlen(buffer) );
|
||||
if(ret < 0)
|
||||
{
|
||||
printf ( "write failed\n" );
|
||||
goto ERR;
|
||||
}
|
||||
if(get_pcie_mode_debug)printf("write %d\n", ret);
|
||||
|
||||
FD_ZERO ( &readfds );
|
||||
FD_SET ( fd, &readfds );
|
||||
|
||||
while(1)
|
||||
{
|
||||
timeout.tv_sec = timeoutVal;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
ret = select ( fd+1, &readfds, ( fd_set * ) 0, ( fd_set * ) 0, &timeout );
|
||||
if(ret > 0)
|
||||
{
|
||||
ret = read ( fd, buffer+totallen, sizeof(buffer)-totallen-1 );
|
||||
if(ret < 0)
|
||||
{
|
||||
printf ( "read failed\n" );
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
totallen += ret;
|
||||
buffer[totallen] = '\0';
|
||||
if(get_pcie_mode_debug)printf("read %d(%s)\n", ret, &buffer[totallen-ret]);
|
||||
if(totallen == sizeof(buffer)-1)
|
||||
break;
|
||||
|
||||
if(strstr(buffer,"\nOK") || strstr(buffer,"\nERROR")
|
||||
|| strstr(buffer,"\n+CME ERROR:") || strstr(buffer,"\n+CMS ERROR:"))
|
||||
{
|
||||
if(get_pcie_mode_debug)printf("match OK/ERROR");
|
||||
if(get_pcie_mode_debug)printf("%s", buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ( "select timeout\n" );
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tcsetattr(fd, TCSAFLUSH, &tiosfd);
|
||||
//printf("buffer:\n %s\n", buffer);
|
||||
printf("%s\n", buffer);
|
||||
if(strstr(buffer,"\nERROR") || strstr(buffer,"\n+CME ERROR:") || strstr(buffer,"\n+CMS ERROR:"))
|
||||
goto ERR;
|
||||
|
||||
close ( fd );
|
||||
return 0;
|
||||
ERR:
|
||||
if(fd > 0)
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
#ifndef __QUERY_PCIE_MODE__
|
||||
#define __QUERY_PCIE_MODE__
|
||||
|
||||
extern int speed_arr[14];
|
||||
extern int name_arr[14];
|
||||
|
||||
extern int get_pcie_mode_debug;
|
||||
|
||||
extern int get_private_gateway_debug;
|
||||
|
||||
extern int xset1(int fd, struct termios *tio, const char *device);
|
||||
|
||||
// set raw tty mode
|
||||
extern void xget1(int fd, struct termios *t, struct termios *oldt);
|
||||
extern int get_pcie_mode();
|
||||
|
||||
#endif
|
||||
@ -1,289 +0,0 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <endian.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "QMIThread.h"
|
||||
#include "util.h"
|
||||
|
||||
static int dibbler_client_alive = 0;
|
||||
|
||||
static int fibo_system(const char *shell_cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
dbg_time("%s", shell_cmd);
|
||||
ret = system(shell_cmd);
|
||||
if (ret) {
|
||||
// dbg_time("Fail to system(\"%s\") = %d, errno: %d (%s)", shell_cmd,
|
||||
// ret, errno, strerror(errno));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fibo_set_mtu(const char *ifname, int ifru_mtu)
|
||||
{
|
||||
int inet_sock;
|
||||
struct ifreq ifr;
|
||||
|
||||
inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (inet_sock > 0) {
|
||||
strcpy(ifr.ifr_name, ifname);
|
||||
|
||||
if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) {
|
||||
if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) {
|
||||
dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu,
|
||||
ifru_mtu);
|
||||
ifr.ifr_ifru.ifru_mtu = ifru_mtu;
|
||||
ioctl(inet_sock, SIOCSIFMTU, &ifr);
|
||||
}
|
||||
}
|
||||
|
||||
close(inet_sock);
|
||||
}
|
||||
}
|
||||
|
||||
static void *udhcpc_thread_function(void *arg)
|
||||
{
|
||||
FILE *udhcpc_fp;
|
||||
char *udhcpc_cmd = (char *)arg;
|
||||
|
||||
if (udhcpc_cmd == NULL)
|
||||
return NULL;
|
||||
|
||||
dbg_time("%s", udhcpc_cmd);
|
||||
udhcpc_fp = popen(udhcpc_cmd, "r");
|
||||
free(udhcpc_cmd);
|
||||
if (udhcpc_fp) {
|
||||
char buf[0xff];
|
||||
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
while ((fgets(buf, sizeof(buf) - 1, udhcpc_fp)) != NULL) {
|
||||
if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n'))
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
dbg_time("%s", buf);
|
||||
}
|
||||
|
||||
pclose(udhcpc_fp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void fibo_set_driver_link_state(PROFILE_T *profile, int link_state)
|
||||
{
|
||||
char link_file[128];
|
||||
int fd;
|
||||
int new_state = 0;
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state",
|
||||
profile->usbnet_adapter);
|
||||
fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (fd == -1) {
|
||||
if (errno != ENOENT)
|
||||
dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno,
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (profile->qmap_mode <= 1)
|
||||
new_state = !!link_state;
|
||||
else {
|
||||
// 0x80 means link off this pdp
|
||||
new_state = (link_state ? 0x00 : 0x80) + profile->pdp;
|
||||
}
|
||||
|
||||
snprintf(link_file, sizeof(link_file), "%d\n", new_state);
|
||||
write(fd, link_file, sizeof(link_file));
|
||||
|
||||
if (link_state == 0 && profile->qmap_mode > 1) {
|
||||
size_t rc;
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
rc = read(fd, link_file, sizeof(link_file));
|
||||
if (rc > 1 && (!strcasecmp(link_file, "0\n") ||
|
||||
!strcasecmp(link_file, "0x0\n"))) {
|
||||
// snprintf(link_file, sizeof(link_file), "busybox ifconfig %s down",
|
||||
// profile->usbnet_adapter);
|
||||
// fibo_system(link_file);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int fibo_raw_ip_mode_check(const char *ifname)
|
||||
{
|
||||
int fd;
|
||||
char raw_ip[128];
|
||||
char shell_cmd[128];
|
||||
char mode[2] = "X";
|
||||
int mode_change = 0;
|
||||
|
||||
snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname);
|
||||
if (access(raw_ip, F_OK))
|
||||
return 0;
|
||||
|
||||
fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (fd < 0) {
|
||||
dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__,
|
||||
raw_ip, errno, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
read(fd, mode, 2);
|
||||
if (mode[0] == '0' || mode[0] == 'N') {
|
||||
snprintf(shell_cmd, sizeof(shell_cmd), "busybox ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname);
|
||||
mode[0] = 'Y';
|
||||
write(fd, mode, 2);
|
||||
mode_change = 1;
|
||||
snprintf(shell_cmd, sizeof(shell_cmd), "busybox ifconfig %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return mode_change;
|
||||
}
|
||||
|
||||
void udhcpc_start(PROFILE_T *profile)
|
||||
{
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char shell_cmd[128];
|
||||
|
||||
fibo_set_driver_link_state(profile, 1);
|
||||
if (profile->qmapnet_adapter) {
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
dbg_time("1 %s", profile->qmichannel);
|
||||
if (qmidev_is_qmiwwan(profile->qmichannel)) {
|
||||
dbg_time("2 %s", ifname);
|
||||
fibo_raw_ip_mode_check(ifname);
|
||||
}
|
||||
|
||||
if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) {
|
||||
fibo_set_mtu(ifname, (profile->ipv4.Mtu));
|
||||
}
|
||||
|
||||
fibo_system("echo 1 > /sys/module/fibo_mhi/parameters/macaddr_check");
|
||||
|
||||
//begin modified by zhangkaibo fix ipv6 dial process flow. mantis 0048789 20200605
|
||||
// if (strcmp(ifname, profile->usbnet_adapter)) {
|
||||
// snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s up",
|
||||
// profile->usbnet_adapter);
|
||||
// fibo_system(shell_cmd);
|
||||
// }
|
||||
//begin modified by zhangkaibo fix ipv6 dial process flow. mantis 0048789 20200605
|
||||
// For IPv6, down & up will send protocol packets, and that's needed.
|
||||
if (profile->ipv6_flag) {
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
//begin modified by zhangming Added NOARP and Multilcast on flag bit commands. mantis 0050106 20200713
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s arp off multicast on", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
//begin modified by zhangming Added NOARP and Multilcast on flag bit commands. mantis 0050106 20200713
|
||||
//Modified unicom dual stack dialing unsuccessful problem
|
||||
|
||||
// for bridge mode, only one public IP, so do udhcpc manually
|
||||
if (fibo_bridge_mode_detect(profile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do DHCP using busybox tools */
|
||||
{
|
||||
char udhcpc_cmd[128];
|
||||
pthread_attr_t udhcpc_thread_attr;
|
||||
pthread_t udhcpc_thread_id;
|
||||
|
||||
pthread_attr_init(&udhcpc_thread_attr);
|
||||
pthread_attr_setdetachstate(&udhcpc_thread_attr,
|
||||
PTHREAD_CREATE_DETACHED);
|
||||
|
||||
if (profile->ipv4.Address) {
|
||||
if (access("/usr/share/udhcpc/default.script", X_OK)) {
|
||||
dbg_time(
|
||||
"Fail to access /usr/share/udhcpc/default.script, "
|
||||
"errno: %d (%s)",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
|
||||
//-f,--foreground Run in foreground
|
||||
//-b,--background Background if lease is not obtained
|
||||
//-n,--now Exit if lease is not obtained
|
||||
//-q,--quit Exit after obtaining lease
|
||||
//-t,--retries N Send up to N discover packets (default 3)
|
||||
snprintf(udhcpc_cmd, sizeof(udhcpc_cmd),
|
||||
"busybox udhcpc -f -n -q -t 5 -i %s", ifname);
|
||||
|
||||
if (!access("/lib/netifd/dhcp.script", X_OK) &&
|
||||
!access("/sbin/ifup", X_OK) &&
|
||||
!access("/sbin/ifstatus", X_OK)) {
|
||||
dbg_time("you are use OpenWrt?");
|
||||
dbg_time("should not calling udhcpc manually?");
|
||||
dbg_time("should modify /etc/config/network as below?");
|
||||
dbg_time("config interface wan");
|
||||
dbg_time("\toption ifname %s", ifname);
|
||||
dbg_time("\toption proto dhcp");
|
||||
dbg_time(
|
||||
"should use \"/sbin/ifstaus wan\" to check %s 's status?",
|
||||
ifname);
|
||||
}
|
||||
|
||||
pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function,
|
||||
(void *)strdup(udhcpc_cmd));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) {
|
||||
// module do not support DHCPv6, only support 'Router Solicit'
|
||||
// and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding,
|
||||
// Kernel do not send RS
|
||||
const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding";
|
||||
int forward_fd = open(forward_file, O_RDONLY);
|
||||
if (forward_fd > 0) {
|
||||
char forward_state[2];
|
||||
read(forward_fd, forward_state, 2);
|
||||
if (forward_state[0] == '1') {
|
||||
dbg_time(
|
||||
"%s enabled, kernel maybe donot send 'Router Solicit'",
|
||||
forward_file);
|
||||
}
|
||||
close(forward_fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void udhcpc_stop(PROFILE_T *profile)
|
||||
{
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char shell_cmd[128];
|
||||
char reset_ip[128];
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
if (profile->qmapnet_adapter) {
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
|
||||
if (dibbler_client_alive) {
|
||||
system("killall dibbler-client");
|
||||
dibbler_client_alive = 0;
|
||||
}
|
||||
//snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s down",
|
||||
// profile->usbnet_adapter);
|
||||
//fibo_system(shell_cmd);
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
snprintf(reset_ip, sizeof(reset_ip) - 1, "busybox ifconfig %s 0.0.0.0", ifname);
|
||||
fibo_system(reset_ip);
|
||||
}
|
||||
@ -1,421 +0,0 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <endian.h>
|
||||
|
||||
#include "libmnl/ifutils.h"
|
||||
#include "libmnl/dhcp/dhcp.h"
|
||||
#include "util.h"
|
||||
#include "QMIThread.h"
|
||||
|
||||
static int fibo_system(const char *shell_cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
dbg_time("%s", shell_cmd);
|
||||
ret = system(shell_cmd);
|
||||
if (ret) {
|
||||
// dbg_time("Fail to system(\"%s\") = %d, errno: %d (%s)", shell_cmd,
|
||||
// ret, errno, strerror(errno));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fibo_raw_ip_mode_check(const char *ifname)
|
||||
{
|
||||
int fd;
|
||||
char raw_ip[128];
|
||||
char mode[2] = "X";
|
||||
int mode_change = 0;
|
||||
|
||||
snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname);
|
||||
if (access(raw_ip, F_OK))
|
||||
return 0;
|
||||
|
||||
fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (fd < 0)
|
||||
{
|
||||
dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
read(fd, mode, 2);
|
||||
if (mode[0] == '0' || mode[0] == 'N')
|
||||
{
|
||||
if_link_down(ifname);
|
||||
dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname);
|
||||
mode[0] = 'Y';
|
||||
write(fd, mode, 2);
|
||||
mode_change = 1;
|
||||
if_link_up(ifname);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return mode_change;
|
||||
}
|
||||
|
||||
static void fibo_set_driver_link_state(PROFILE_T *profile, int link_state)
|
||||
{
|
||||
char link_file[128];
|
||||
int fd;
|
||||
int new_state = 0;
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter);
|
||||
fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (fd == -1)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (profile->qmap_mode <= 1)
|
||||
new_state = !!link_state;
|
||||
else
|
||||
{
|
||||
//0x80 means link off this pdp
|
||||
new_state = (link_state ? 0x00 : 0x80) + profile->pdp;
|
||||
}
|
||||
|
||||
snprintf(link_file, sizeof(link_file), "%d\n", new_state);
|
||||
write(fd, link_file, sizeof(link_file));
|
||||
|
||||
if (link_state == 0 && profile->qmap_mode > 1)
|
||||
{
|
||||
size_t rc;
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
rc = read(fd, link_file, sizeof(link_file));
|
||||
if (rc > 1 && (!strcasecmp(link_file, "0\n") || !strcasecmp(link_file, "0x0\n")))
|
||||
{
|
||||
// if_link_down(profile->usbnet_adapter);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void udhcpc_start(PROFILE_T *profile)
|
||||
{
|
||||
//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char shell_cmd[512];
|
||||
|
||||
fibo_set_driver_link_state(profile, 1);
|
||||
fibo_raw_ip_mode_check(ifname);
|
||||
|
||||
if (profile->qmapnet_adapter)
|
||||
{
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu)
|
||||
{
|
||||
if_set_mtu(ifname, (profile->ipv4.Mtu));
|
||||
}
|
||||
|
||||
if (strcmp(ifname, profile->usbnet_adapter))
|
||||
{
|
||||
//if_link_up(profile->usbnet_adapter);
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s up", profile->usbnet_adapter);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837
|
||||
if_link_up(ifname);
|
||||
|
||||
#if 1 //for bridge mode, only one public IP, so do udhcpc manually
|
||||
if (fibo_bridge_mode_detect(profile))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// if use DHCP(should make with ${DHCP} src files)
|
||||
// do_dhcp(ifname);
|
||||
// return 0;
|
||||
/* IPv4 Addr Info */
|
||||
if (profile->ipv4.Address)
|
||||
{
|
||||
dbg_time("IPv4 MTU: %d", profile->ipv4.Mtu);
|
||||
dbg_time("IPv4 Address: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Address)));
|
||||
dbg_time("IPv4 Netmask: %d", mask_to_prefix_v4(ntohl(profile->ipv4.SubnetMask)));
|
||||
dbg_time("IPv4 Gateway: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway)));
|
||||
dbg_time("IPv4 DNS1: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary)));
|
||||
dbg_time("IPv4 DNS2: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary)));
|
||||
if_set_network_v4(ifname, ntohl(profile->ipv4.Address),
|
||||
mask_to_prefix_v4(profile->ipv4.SubnetMask),
|
||||
ntohl(profile->ipv4.Gateway),
|
||||
ntohl(profile->ipv4.DnsPrimary),
|
||||
ntohl(profile->ipv4.DnsSecondary));
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_time("The IPv4 Address in profile is NULL");
|
||||
}
|
||||
|
||||
if (profile->ipv6.Address && (profile->ipv6.PrefixLengthIPAddr != 0))
|
||||
{
|
||||
//module do not support DHCPv6, only support 'Router Solicit'
|
||||
//and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS
|
||||
const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding";
|
||||
int forward_fd = open(forward_file, O_RDONLY);
|
||||
if (forward_fd > 0)
|
||||
{
|
||||
char forward_state[2];
|
||||
read(forward_fd, forward_state, 2);
|
||||
if (forward_state[0] == '1')
|
||||
{
|
||||
dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file);
|
||||
}
|
||||
close(forward_fd);
|
||||
}
|
||||
|
||||
dbg_time("IPv6 MTU: %d", profile->ipv6.Mtu);
|
||||
dbg_time("IPv6 Address: %s", ipaddr_to_string_v6(profile->ipv6.Address));
|
||||
dbg_time("IPv6 PrefixLengthIPAddr: %d", profile->ipv6.PrefixLengthIPAddr);
|
||||
dbg_time("IPv6 Gateway: %s", ipaddr_to_string_v6(profile->ipv6.Gateway));
|
||||
dbg_time("IPv6 DNS1: %s", ipaddr_to_string_v6(profile->ipv6.DnsPrimary));
|
||||
dbg_time("IPv6 DNS2: %s", ipaddr_to_string_v6(profile->ipv6.DnsSecondary));
|
||||
if_set_network_v6(ifname, profile->ipv6.Address, profile->ipv6.PrefixLengthIPAddr,
|
||||
profile->ipv6.Gateway, profile->ipv6.DnsPrimary, profile->ipv6.DnsSecondary);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_time("The IPv6 Address in profile is NULL");
|
||||
}
|
||||
}
|
||||
|
||||
void udhcpc_stop(PROFILE_T *profile)
|
||||
{
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
fibo_set_driver_link_state(profile, 0);
|
||||
|
||||
if (profile->qmapnet_adapter)
|
||||
{
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
|
||||
if_flush_v4_addr(ifname);
|
||||
if_flush_v6_addr(ifname);
|
||||
if_link_down(ifname);
|
||||
}
|
||||
|
||||
static void fibo_set_mtu(const char *ifname, int ifru_mtu) {
|
||||
int inet_sock;
|
||||
struct ifreq ifr;
|
||||
|
||||
inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (inet_sock > 0) {
|
||||
strcpy(ifr.ifr_name, ifname);
|
||||
|
||||
if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) {
|
||||
if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) {
|
||||
dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu , ifru_mtu);
|
||||
ifr.ifr_ifru.ifru_mtu = ifru_mtu;
|
||||
ioctl(inet_sock, SIOCSIFMTU, &ifr);
|
||||
}
|
||||
}
|
||||
|
||||
close(inet_sock);
|
||||
}
|
||||
}
|
||||
|
||||
static void* udhcpc_thread_function(void* arg) {
|
||||
FILE * udhcpc_fp;
|
||||
char *udhcpc_cmd = (char *)arg;
|
||||
|
||||
if (udhcpc_cmd == NULL)
|
||||
return NULL;
|
||||
|
||||
dbg_time("%s", udhcpc_cmd);
|
||||
udhcpc_fp = popen(udhcpc_cmd, "r");
|
||||
free(udhcpc_cmd);
|
||||
if (udhcpc_fp) {
|
||||
char buf[0xff];
|
||||
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
while((fgets(buf, sizeof(buf)-1, udhcpc_fp)) != NULL) {
|
||||
if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n'))
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
dbg_time("%s", buf);
|
||||
}
|
||||
|
||||
pclose(udhcpc_fp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void udhcpc_start_pcie(PROFILE_T *profile) {
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char sub_intf_name[100] = {0};
|
||||
int intf_id = 0;
|
||||
char shell_cmd[512];
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
if (profile->qmapnet_adapter) {
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
|
||||
if (profile->muxid > 0x81)
|
||||
{
|
||||
intf_id = profile->muxid - 0x81;
|
||||
snprintf(sub_intf_name, sizeof(sub_intf_name) - 1, "%s.%d", ifname, intf_id);
|
||||
}
|
||||
|
||||
if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) {
|
||||
fibo_set_mtu(ifname, (profile->ipv4.Mtu));
|
||||
}
|
||||
|
||||
fibo_system("echo 1 > /sys/module/fibo_mhi/parameters/macaddr_check");
|
||||
|
||||
if (strcmp(ifname, profile->usbnet_adapter)) {
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s up", profile->usbnet_adapter);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
|
||||
// For IPv6, down & up will send protocol packets, and that's needed.
|
||||
if (profile->ipv6_flag && profile->muxid <= 0x81) {
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
//for bridge mode, only one public IP, so do udhcpc manually
|
||||
if (fibo_bridge_mode_detect(profile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do DHCP using busybox tools */
|
||||
{
|
||||
char udhcpc_cmd[128];
|
||||
pthread_attr_t udhcpc_thread_attr;
|
||||
pthread_t udhcpc_thread_id;
|
||||
|
||||
pthread_attr_init(&udhcpc_thread_attr);
|
||||
pthread_attr_setdetachstate(&udhcpc_thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
if (profile->ipv4.Address)
|
||||
{
|
||||
char v4add_str[32] = {0};
|
||||
char v4gw_str[32] = {0};
|
||||
char v4_netmask_str[32] = {0};
|
||||
uint32_t Address = ntohl(profile->ipv4.Address);
|
||||
uint32_t Gateway = ntohl(profile->ipv4.Gateway);
|
||||
uint32_t SubnetMask = ntohl(profile->ipv4.SubnetMask);
|
||||
inet_ntop(AF_INET, &Address, v4add_str, sizeof(v4add_str));
|
||||
inet_ntop(AF_INET, &Gateway, v4gw_str, sizeof(v4gw_str));
|
||||
inet_ntop(AF_INET, &SubnetMask, v4_netmask_str, sizeof(v4_netmask_str));
|
||||
|
||||
if (profile->muxid == 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s %s netmask %s", ifname, v4add_str, v4_netmask_str);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "route add default gw %s dev %s", v4gw_str, ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
else if (profile->muxid > 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link add link %s name %s type vlan id %d", ifname, sub_intf_name, intf_id);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", sub_intf_name);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s %s netmask %s", sub_intf_name, v4add_str, v4_netmask_str);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
if (profile->ipv6.PrefixLengthIPAddr)
|
||||
{
|
||||
//module do not support DHCPv6, only support 'Router Solicit'
|
||||
//and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS
|
||||
const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding";
|
||||
int forward_fd = open(forward_file, O_RDONLY);
|
||||
if (forward_fd > 0) {
|
||||
char forward_state[2];
|
||||
read(forward_fd, forward_state, 2);
|
||||
if (forward_state[0] == '1') {
|
||||
dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file);
|
||||
}
|
||||
close(forward_fd);
|
||||
}
|
||||
|
||||
{
|
||||
char v6add_str[100] = {0};
|
||||
char v6gw_str[100] = {0};
|
||||
inet_ntop(AF_INET6, profile->ipv6.Address, v6add_str, sizeof(v6add_str));
|
||||
inet_ntop(AF_INET6, profile->ipv6.Gateway, v6gw_str, sizeof(v6gw_str));
|
||||
|
||||
if (profile->muxid == 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s add %s/%d", ifname, v6add_str, profile->ipv6.PrefixLengthIPAddr);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "route -A inet6 add ::/0 gw %s dev %s", v6gw_str, ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
else if (profile->muxid > 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link add link %s name %s type vlan id %d", ifname, sub_intf_name, intf_id);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", sub_intf_name);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s add %s/%d", sub_intf_name, v6add_str, profile->ipv6.PrefixLengthIPAddr);
|
||||
fibo_system(shell_cmd);
|
||||
/* start 2021-01-21 add by haopengfei to fix mantis 69056 */
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "route -A inet6 add ::/0 gw %s dev %s", v6gw_str, sub_intf_name);
|
||||
fibo_system(shell_cmd);
|
||||
/* end 2021-01-21 add by haopengfei to fix mantis 69056 */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void udhcpc_stop_pcie(PROFILE_T *profile) {
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char shell_cmd[128];
|
||||
char reset_ip[128];
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
if (profile->qmapnet_adapter) {
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
|
||||
if (profile->muxid == 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
snprintf(reset_ip, sizeof(reset_ip) - 1, "ifconfig %s 0.0.0.0", ifname);
|
||||
fibo_system(reset_ip);
|
||||
}
|
||||
else if (profile->muxid > 0x81)
|
||||
{
|
||||
char sub_intf_name[100];
|
||||
int intf_id = profile->muxid - 0x81;
|
||||
snprintf(sub_intf_name, sizeof(sub_intf_name) - 1, "%s.%d", ifname, intf_id);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link del link dev %s", sub_intf_name);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,142 +0,0 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "QMIThread.h"
|
||||
|
||||
#if defined(__STDC__)
|
||||
#include <stdarg.h>
|
||||
#define __V(x) x
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#define __V(x) (va_alist) va_dcl
|
||||
#define const
|
||||
#define volatile
|
||||
#endif
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#define is_bigendian() ((*(char *)&i) == 0)
|
||||
FILE *logfilefp = NULL;
|
||||
static pthread_mutex_t printfMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static char line[1024];
|
||||
const int i = 1;
|
||||
|
||||
// defined in atchannel.c
|
||||
static void setTimespecRelative(struct timespec *p_ts, long long msec)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, (struct timezone *)NULL);
|
||||
|
||||
/* what's really funny about this is that I know
|
||||
pthread_cond_timedwait just turns around and makes this
|
||||
a relative time again */
|
||||
p_ts->tv_sec = tv.tv_sec + (msec / 1000);
|
||||
p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L) * 1000L;
|
||||
}
|
||||
|
||||
int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
unsigned msecs)
|
||||
{
|
||||
if (msecs != 0) {
|
||||
struct timespec ts;
|
||||
setTimespecRelative(&ts, msecs);
|
||||
return pthread_cond_timedwait(cond, mutex, &ts);
|
||||
} else {
|
||||
return pthread_cond_wait(cond, mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_time(void)
|
||||
{
|
||||
static char time_buf[50];
|
||||
struct timeval tv;
|
||||
time_t time;
|
||||
suseconds_t millitm;
|
||||
struct tm *ti;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
time = tv.tv_sec;
|
||||
millitm = (tv.tv_usec + 500) / 1000;
|
||||
|
||||
if (millitm == 1000) {
|
||||
++time;
|
||||
millitm = 0;
|
||||
}
|
||||
|
||||
ti = localtime(&time);
|
||||
sprintf(time_buf, "[%02d-%02d_%02d:%02d:%02d:%03d]", ti->tm_mon + 1,
|
||||
ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm);
|
||||
return time_buf;
|
||||
}
|
||||
|
||||
void dbg_time(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
pthread_mutex_lock(&printfMutex);
|
||||
|
||||
snprintf(line, sizeof(line), "%s ", get_time());
|
||||
|
||||
vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, args);
|
||||
fprintf(stdout, "%s\n", line);
|
||||
|
||||
if (logfilefp) {
|
||||
fprintf(logfilefp, "%s\n", line);
|
||||
}
|
||||
fflush(logfilefp);
|
||||
pthread_mutex_unlock(&printfMutex);
|
||||
}
|
||||
|
||||
USHORT le16_to_cpu(USHORT v16)
|
||||
{
|
||||
USHORT tmp = v16;
|
||||
if (is_bigendian()) {
|
||||
unsigned char *s = (unsigned char *)(&v16);
|
||||
unsigned char *d = (unsigned char *)(&tmp);
|
||||
d[0] = s[1];
|
||||
d[1] = s[0];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
UINT le32_to_cpu(UINT v32)
|
||||
{
|
||||
UINT tmp = v32;
|
||||
if (is_bigendian()) {
|
||||
unsigned char *s = (unsigned char *)(&v32);
|
||||
unsigned char *d = (unsigned char *)(&tmp);
|
||||
d[0] = s[3];
|
||||
d[1] = s[2];
|
||||
d[2] = s[1];
|
||||
d[3] = s[0];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
USHORT cpu_to_le16(USHORT v16)
|
||||
{
|
||||
USHORT tmp = v16;
|
||||
if (is_bigendian()) {
|
||||
unsigned char *s = (unsigned char *)(&v16);
|
||||
unsigned char *d = (unsigned char *)(&tmp);
|
||||
d[0] = s[1];
|
||||
d[1] = s[0];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
UINT cpu_to_le32(UINT v32)
|
||||
{
|
||||
UINT tmp = v32;
|
||||
if (is_bigendian()) {
|
||||
unsigned char *s = (unsigned char *)(&v32);
|
||||
unsigned char *d = (unsigned char *)(&tmp);
|
||||
d[0] = s[3];
|
||||
d[1] = s[2];
|
||||
d[2] = s[1];
|
||||
d[3] = s[0];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct listnode {
|
||||
struct listnode *next;
|
||||
struct listnode *prev;
|
||||
};
|
||||
|
||||
#define node_to_item(node, container, member) \
|
||||
(container *)(((char *)(node)) - offsetof(container, member))
|
||||
|
||||
#define list_declare(name) \
|
||||
struct listnode name = { \
|
||||
.next = &name, \
|
||||
.prev = &name, \
|
||||
}
|
||||
|
||||
#define list_for_each(node, list) \
|
||||
for (node = (list)->next; node != (list); node = node->next)
|
||||
|
||||
#define list_for_each_reverse(node, list) \
|
||||
for (node = (list)->prev; node != (list); node = node->prev)
|
||||
void dbg_time(const char *fmt, ...);
|
||||
void list_init(struct listnode *list);
|
||||
void list_add_tail(struct listnode *list, struct listnode *item);
|
||||
void list_add_head(struct listnode *head, struct listnode *item);
|
||||
void list_remove(struct listnode *item);
|
||||
|
||||
#define list_empty(list) ((list) == (list)->next)
|
||||
#define list_head(list) ((list)->next)
|
||||
#define list_tail(list) ((list)->prev)
|
||||
|
||||
int epoll_register(int epoll_fd, int fd, unsigned int events);
|
||||
int epoll_deregister(int epoll_fd, int fd);
|
||||
#endif
|
||||
@ -1,47 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=qmi_wwan_f
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=3
|
||||
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define KernelPackage/qmi_wwan_f
|
||||
SUBMENU:=WWAN Support
|
||||
TITLE:=Fibocom Linux USB QMI WWAN Driver
|
||||
DEPENDS:=+kmod-usb-net +kmod-usb-wdm
|
||||
FILES:=$(PKG_BUILD_DIR)/qmi_wwan_f.ko
|
||||
AUTOLOAD:=$(call AutoLoad,82,qmi_wwan_f)
|
||||
endef
|
||||
|
||||
define KernelPackage/qmi_wwan_f/description
|
||||
Fibocom Linux USB QMI WWAN Driver
|
||||
endef
|
||||
|
||||
MAKE_OPTS:= \
|
||||
ARCH="$(LINUX_KARCH)" \
|
||||
CROSS_COMPILE="$(TARGET_CROSS)" \
|
||||
CXXFLAGS="$(TARGET_CXXFLAGS)" \
|
||||
M="$(PKG_BUILD_DIR)" \
|
||||
$(EXTRA_KCONFIG)
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C "$(LINUX_DIR)" \
|
||||
$(MAKE_OPTS) \
|
||||
modules
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,qmi_wwan_f))
|
||||
@ -1,38 +0,0 @@
|
||||
obj-m += qmi_wwan_f.o
|
||||
|
||||
PWD := $(shell pwd)
|
||||
OUTPUTDIR=/lib/modules/`uname -r`/kernel/drivers/net/usb/
|
||||
|
||||
ifeq ($(ARCH),)
|
||||
ARCH := $(shell uname -m)
|
||||
endif
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE :=
|
||||
endif
|
||||
ifeq ($(KDIR),)
|
||||
KDIR := /lib/modules/$(shell uname -r)/build
|
||||
ifeq ($(ARCH),i686)
|
||||
ifeq ($(wildcard $KDIR/arch/$ARCH),)
|
||||
ARCH=i386
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(findstring &,${PWD}),)
|
||||
$(warning "${PWD}")
|
||||
$(warning "current directory contain special char '&' !")
|
||||
$(error "please remove it!")
|
||||
endif
|
||||
|
||||
default:
|
||||
$(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) modules
|
||||
|
||||
install: default
|
||||
cp $(PWD)/qmi_wwan_f.ko /lib/modules/$(shell uname -r)/kernel/drivers/net/usb/
|
||||
depmod
|
||||
modprobe -r qmi_wwan_f
|
||||
modprobe -r qmi_wwan
|
||||
modprobe qmi_wwan_f
|
||||
clean:
|
||||
rm -rf *~ .tmp_versions modules.order Module.symvers
|
||||
find . -type f -name "*~" -o -name "*.o" -o -name "*.ko" -o -name "*.cmd" -o -name "*.mod.c" | xargs rm -rf
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,76 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015-2016 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=adbyby
|
||||
PKG_VERSION:=2.7
|
||||
PKG_RELEASE:=20200315
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/adbyby
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Powerful adblock module to block ad.
|
||||
DEPENDS:=@(i386||x86_64||arm||mipsel||mips||aarch64)
|
||||
URL:=http://www.adbyby.com/
|
||||
endef
|
||||
|
||||
define Package/adbyby/description
|
||||
Adbyby is a powerful adblock module to block ad,just like adblock.
|
||||
endef
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
ADBYBY_DIR:=amd64
|
||||
endif
|
||||
ifeq ($(ARCH),mipsel)
|
||||
ADBYBY_DIR:=mipsle
|
||||
endif
|
||||
ifeq ($(ARCH),mips)
|
||||
ADBYBY_DIR:=mips
|
||||
endif
|
||||
ifeq ($(ARCH),i386)
|
||||
ADBYBY_DIR:=x86
|
||||
endif
|
||||
ifeq ($(ARCH),arm)
|
||||
ADBYBY_DIR:=armv7
|
||||
ifeq ($(BOARD),bcm53xx)
|
||||
ADBYBY_DIR:=arm
|
||||
endif
|
||||
ifeq ($(BOARD),kirkwood)
|
||||
ADBYBY_DIR:=arm
|
||||
endif
|
||||
endif
|
||||
ifeq ($(ARCH),aarch64)
|
||||
ADBYBY_DIR:=armv7
|
||||
endif
|
||||
|
||||
define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/adbyby/install
|
||||
$(INSTALL_DIR) $(1)/usr/share/adbyby
|
||||
$(INSTALL_BIN) ./files/adbyby.sh $(1)/usr/share/adbyby/
|
||||
$(INSTALL_CONF) ./files/adhook.ini $(1)/usr/share/adbyby/
|
||||
$(INSTALL_CONF) ./files/user.action $(1)/usr/share/adbyby/
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/share/adbyby/data
|
||||
$(INSTALL_DATA) ./files/data/* $(1)/usr/share/adbyby/data/
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/share/adbyby/doc
|
||||
$(INSTALL_DATA) ./files/doc/* $(1)/usr/share/adbyby/doc/
|
||||
|
||||
$(INSTALL_BIN) ./files/$(ADBYBY_DIR)/adbyby $(1)/usr/share/adbyby/adbyby
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,adbyby))
|
||||
@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
PROG_PATH=/usr/share/adbyby
|
||||
err=0
|
||||
until [ $err -ge 5 ]; do
|
||||
if [ -n "$(pgrep $PROG_PATH/adbyby)" ]; then
|
||||
iptables-save | grep ADBYBY >/dev/null || \
|
||||
/etc/init.d/adbyby add_rule
|
||||
sleep 10
|
||||
err=0
|
||||
else
|
||||
$PROG_PATH/adbyby --no-daemon &>/dev/null &
|
||||
sleep 1
|
||||
err=$((err+1))
|
||||
fi
|
||||
done
|
||||
/etc/init.d/adbyby del_rule
|
||||
@ -1,14 +0,0 @@
|
||||
[cfg]
|
||||
### 2.1 ###
|
||||
listen-address=0.0.0.0:8118
|
||||
buffer-limit=1024
|
||||
keep-alive-timeout=30
|
||||
socket-timeout=60
|
||||
### 2.5 ###
|
||||
max_client_connections=0
|
||||
### 2.6 ###
|
||||
stack_size=200
|
||||
auto_restart=0
|
||||
### 2.7 ###
|
||||
debug=0
|
||||
ipset=0
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,25 +0,0 @@
|
||||
! -----¸üÐÂʱ¼ä: 2018-10-08 23:07:52 by:xwhyc-----
|
||||
.php?ad=
|
||||
/99rejs/js
|
||||
/agetsou.js^
|
||||
/c@*!25.js|$script
|
||||
/cococ-66/$script
|
||||
/defaultts.tc.qq.com/*.ts?index=0&start=0&
|
||||
/defaultts.tc.qq.com/*.ts?index=0&start=0&end=*&ver=4
|
||||
/gg_js/
|
||||
/imgs.js?t=
|
||||
/js/adtop.js|
|
||||
/js/guanggao_gg.js?d=
|
||||
/js/sss/ad.js
|
||||
/static/js/aall.js
|
||||
/unionjs/$script
|
||||
/variety.tc.qq.com/*.mp4^*fmt=hd
|
||||
/variety.tc.qq.com/*.mp4^*fmt=shd
|
||||
/video.dispatch.tc.qq.com/*.mp4^*sdtfrom=
|
||||
/view/image/QT_HY.jpg?t=
|
||||
/view/js/slade.js|$script
|
||||
/vlive.qqvideo.tc.qq.com/*.mp4^*fmt=hd
|
||||
/vlive.qqvideo.tc.qq.com/*.mp4^*fmt=shd
|
||||
/vmind.qqvideo.tc.qq.com/*.mp4^*sdtfrom=
|
||||
/vmindhls.tc.qq.com/*ugc=0&ga=0&gv=0&start=
|
||||
/zzhzgg.js
|
||||
@ -1,15 +0,0 @@
|
||||
! ------------------------------ ADByby 自定义过滤语法简表---------------------------------
|
||||
! -------------- 规则基于abp规则,并进行了字符替换部分的扩展-----------------------------
|
||||
! ABP规则请参考https://adblockplus.org/zh_CN/filters,下面为大致摘要
|
||||
! "!" 为行注释符,注释行以该符号起始作为一行注释语义,用于规则描述
|
||||
! "*" 为字符通配符,能够匹配0长度或任意长度的字符串,该通配符不能与正则语法混用。
|
||||
! "^" 为分隔符,可以是除了字母、数字或者 _ - . % 之外的任何字符。
|
||||
! "|" 为管线符号,来表示地址的最前端或最末端
|
||||
! "||" 为子域通配符,方便匹配主域名下的所有子域。
|
||||
! "~" 为排除标识符,通配符能过滤大多数广告,但同时存在误杀, 可以通过排除标识符修正误杀链接。
|
||||
! "##" 为元素选择器标识符,后面跟需要隐藏元素的CSS样式例如 #ad_id .ad_class
|
||||
!! 元素隐藏暂不支持全局规则和排除规则
|
||||
!! 字符替换扩展
|
||||
! 文本替换选择器标识符,后面跟需要替换的文本数据,格式:$s@模式字符串@替换后的文本@
|
||||
! 支持通配符*和?
|
||||
! -------------------------------------------------------------------------------------------
|
||||
@ -1,30 +0,0 @@
|
||||
! -----更新时间: 2018-10-08 23:06:11 by:xwhyc-----------------------------------------------
|
||||
! -----广告反馈:http://www.adbyby.com/help.htm QQ群: 79547134(满), 364066294(满),470705224(满),534897434,438394572--------------
|
||||
|
||||
|
||||
!-------------------------------------------
|
||||
/showadv/
|
||||
3199.cn###ad640,[id^="ad0"]
|
||||
76fengyun.com###down_box{display:block!important;}.gggg,.ggao
|
||||
9553.com##[class="zm"]
|
||||
962.net##.show_ad,.g-962-ad
|
||||
amazon.cn##.adv-float-div
|
||||
downsx.rocks##.adbox,.Left-ad3_fixed,.google-ad2_fixed
|
||||
edu-acc.cn###doyoo_monitor
|
||||
fx678.com##[class^="adv-"]
|
||||
||76fengyun.com/body22233.js
|
||||
||76fengyun.com/file/$s@onclick="window.open('*');startWait();"@onclick="window.open(document.getElementById('downpage_link').href);startWait();"@
|
||||
||atanx.alicdn.com/t/tanxssp.js?_v=
|
||||
||biquguan.com/guan/$script
|
||||
||djv99sxoqpv11.cloudfront.net
|
||||
||jmxlaser.com
|
||||
||jump2.bdimg.com/p/$s@<div class="l_post l_post_bright j_l_post clearfix ?????????? "@<div style="display:none"@
|
||||
||nxkycx.com
|
||||
||res.jklan.cn/wp-content/themes/tt/js/system.js?ver=$s@function goto()@function xxx()@
|
||||
||tieba.com/p/$s@<div class="l_post l_post_bright j_l_post clearfix ?????????? "@<div style="display:none"@
|
||||
||ychap.com
|
||||
!-----------------------
|
||||
/qkostn.js|
|
||||
|http://mark.l.qq.com/fcgi-bin/get_video_mark_all*&strAdParam=
|
||||
!---------adbyby---------
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
@ -1,10 +0,0 @@
|
||||
;¸üйæÔòurl,dir,size,reverse,reverse
|
||||
http://update.adbyby.com/rule3/lazy.jpg \data\lazy.txt 385337 4 0
|
||||
http://update.adbyby.com/rule3/video.jpg \data\video.txt 1028 4 0
|
||||
http://update.adbyby.com/rule3/user.action \user.action 512 5 0
|
||||
http://update.adbyby.com/rule3/clean.ini \data\clean.ini 2167 0 0
|
||||
http://update.adbyby.com/rule3/adclear.ini \data\adclear.ini 4901 0 0
|
||||
https://github.com/gchangchen/suho/raw/master/adhook.dll \adhook.dll 117248 0 0 2.4.3.2
|
||||
https://github.com/gchangchen/suho/raw/master/adhook64.dll \adhook64.dll 142848 0 0 2.4.3.2
|
||||
https://github.com/gchangchen/suho/raw/master/adbyby.exe \adbyby.exe 1004183 1 0 2.4.4.0
|
||||
|
||||
Binary file not shown.
@ -1,84 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2010-2023 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=autocore
|
||||
PKG_RELEASE:=$(COMMITCOUNT)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
define Package/autocore-arm
|
||||
TITLE:=Arm auto core loadbalance script
|
||||
DEPENDS:=@(arm||aarch64) \
|
||||
+TARGET_bcm27xx:bcm27xx-userland \
|
||||
+TARGET_bcm53xx:nvram +ethtool
|
||||
VARIANT:=arm
|
||||
endef
|
||||
|
||||
define Package/autocore-loongarch64
|
||||
TITLE:=Loongarch64 auto core loadbalance script
|
||||
DEPENDS:=@loongarch64 +bc +ethtool +pciutils
|
||||
VARIANT:=loongarch64
|
||||
endef
|
||||
|
||||
define Package/autocore-x86
|
||||
TITLE:=x86/64 auto core loadbalance script
|
||||
DEPENDS:=@TARGET_x86 +bc +ethtool +lm-sensors +pciutils
|
||||
VARIANT:=x86
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/autocore-arm/install
|
||||
$(INSTALL_DIR) $(1)/etc
|
||||
$(INSTALL_DATA) ./files/arm/index.htm $(1)/etc/index.htm
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/60-autocore-reload-rpcd $(1)/etc/uci-defaults/
|
||||
$(INSTALL_BIN) ./files/arm/090-cover-index_htm $(1)/etc/uci-defaults/
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) ./files/arm/sbin/cpuinfo $(1)/sbin/cpuinfo
|
||||
$(INSTALL_BIN) ./files/arm/sbin/ethinfo $(1)/sbin/ethinfo
|
||||
$(INSTALL_BIN) ./files/arm/sbin/usage $(1)/sbin/usage
|
||||
ifneq ($(filter ipq% %filogic qualcommax%, $(TARGETID)),)
|
||||
$(INSTALL_BIN) ./files/arm/sbin/tempinfo $(1)/sbin/tempinfo
|
||||
endif
|
||||
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
|
||||
$(CP) ./files/luci-mod-status-autocore.json $(1)/usr/share/rpcd/acl.d/
|
||||
endef
|
||||
|
||||
define Package/autocore-loongarch64/install
|
||||
$(INSTALL_DIR) $(1)/etc
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/loongarch64/autocore $(1)/etc/init.d/autocore
|
||||
$(INSTALL_BIN) ./files/60-autocore-reload-rpcd $(1)/etc/uci-defaults/
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) ./files/loongarch64/sbin/cpuinfo $(1)/sbin/cpuinfo
|
||||
$(INSTALL_BIN) ./files/loongarch64/sbin/tempinfo $(1)/sbin/tempinfo
|
||||
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
|
||||
$(CP) ./files/luci-mod-status-autocore.json $(1)/usr/share/rpcd/acl.d/
|
||||
endef
|
||||
|
||||
define Package/autocore-x86/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/x86/autocore $(1)/etc/init.d/autocore
|
||||
$(INSTALL_DIR) $(1)/etc
|
||||
$(INSTALL_DATA) ./files/x86/index.htm $(1)/etc/index.htm
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/60-autocore-reload-rpcd $(1)/etc/uci-defaults/
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(CP) ./files/x86/sbin/* $(1)/sbin
|
||||
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
|
||||
$(CP) ./files/luci-mod-status-autocore.json $(1)/usr/share/rpcd/acl.d/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,autocore-arm))
|
||||
$(eval $(call BuildPackage,autocore-loongarch64))
|
||||
$(eval $(call BuildPackage,autocore-x86))
|
||||
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
/etc/init.d/rpcd restart
|
||||
|
||||
exit 0
|
||||
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -f /etc/index.htm ] && mv /etc/index.htm /usr/lib/lua/luci/view/admin_status/index.htm
|
||||
|
||||
exit 0
|
||||
@ -1,857 +0,0 @@
|
||||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local fs = require "nixio.fs"
|
||||
local util = require "luci.util"
|
||||
local stat = require "luci.tools.status"
|
||||
local ver = require "luci.version"
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
|
||||
local has_ipv6 = fs.access("/usr/sbin/ip6tables")
|
||||
local has_dhcp = fs.access("/etc/config/dhcp")
|
||||
local has_wifi = ((fs.stat("/etc/config/wireless", "size") or 0) > 0)
|
||||
local has_switch = false
|
||||
|
||||
uci:foreach("network", "switch",
|
||||
function(s)
|
||||
has_switch = true
|
||||
return false
|
||||
end)
|
||||
|
||||
local sysinfo = luci.util.ubus("system", "info") or { }
|
||||
local boardinfo = luci.util.ubus("system", "board") or { }
|
||||
local unameinfo = nixio.uname() or { }
|
||||
|
||||
local meminfo = sysinfo.memory or {
|
||||
total = 0,
|
||||
free = 0,
|
||||
buffered = 0,
|
||||
shared = 0
|
||||
}
|
||||
|
||||
local mem_cached = luci.sys.exec("sed -e '/^Cached: /!d; s#Cached: *##; s# kB##g' /proc/meminfo")
|
||||
|
||||
local swapinfo = sysinfo.swap or {
|
||||
total = 0,
|
||||
free = 0
|
||||
}
|
||||
|
||||
local has_dsl = fs.access("/etc/init.d/dsl_control")
|
||||
|
||||
if luci.http.formvalue("status") == "1" then
|
||||
local ntm = require "luci.model.network".init()
|
||||
local wan = ntm:get_wannet()
|
||||
local wan6 = ntm:get_wan6net()
|
||||
|
||||
local conn_count = tonumber(
|
||||
fs.readfile("/proc/sys/net/netfilter/nf_conntrack_count") or "") or 0
|
||||
|
||||
local conn_max = tonumber(luci.sys.exec(
|
||||
"sysctl -n -e net.nf_conntrack_max net.ipv4.netfilter.ip_conntrack_max"
|
||||
):match("%d+")) or 4096
|
||||
|
||||
local user_info = luci.sys.exec("cat /proc/net/arp | grep 'br-lan' | grep '0x2' | wc -l")
|
||||
|
||||
local cpu_usage = luci.sys.exec("/sbin/usage") or "6%"
|
||||
local cpu_info = luci.sys.exec("/sbin/cpuinfo") or "?"
|
||||
local eth_info = luci.sys.exec("ethinfo")
|
||||
|
||||
local rv = {
|
||||
cpuinfo = cpu_info,
|
||||
cpuusage = cpu_usage,
|
||||
ethinfo = eth_info,
|
||||
userinfo = user_info,
|
||||
uptime = sysinfo.uptime or 0,
|
||||
localtime = os.date(),
|
||||
loadavg = sysinfo.load or { 0, 0, 0 },
|
||||
memory = meminfo,
|
||||
memcached = mem_cached,
|
||||
swap = swapinfo,
|
||||
connmax = conn_max,
|
||||
conncount = conn_count,
|
||||
leases = stat.dhcp_leases(),
|
||||
leases6 = stat.dhcp6_leases(),
|
||||
wifinets = stat.wifi_networks()
|
||||
}
|
||||
|
||||
if wan then
|
||||
rv.wan = {
|
||||
ipaddr = wan:ipaddr(),
|
||||
gwaddr = wan:gwaddr(),
|
||||
netmask = wan:netmask(),
|
||||
dns = wan:dnsaddrs(),
|
||||
expires = wan:expires(),
|
||||
uptime = wan:uptime(),
|
||||
proto = wan:proto(),
|
||||
ifname = wan:ifname(),
|
||||
link = wan:adminlink()
|
||||
}
|
||||
end
|
||||
|
||||
if wan6 then
|
||||
rv.wan6 = {
|
||||
ip6addr = wan6:ip6addr(),
|
||||
gw6addr = wan6:gw6addr(),
|
||||
dns = wan6:dns6addrs(),
|
||||
ip6prefix = wan6:ip6prefix(),
|
||||
uptime = wan6:uptime(),
|
||||
proto = wan6:proto(),
|
||||
ifname = wan6:ifname(),
|
||||
link = wan6:adminlink()
|
||||
}
|
||||
end
|
||||
|
||||
if has_dsl then
|
||||
local dsl_stat = luci.sys.exec("/etc/init.d/dsl_control lucistat")
|
||||
local dsl_func = loadstring(dsl_stat)
|
||||
if dsl_func then
|
||||
rv.dsl = dsl_func()
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
|
||||
return
|
||||
elseif luci.http.formvalue("hosts") == "1" then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(luci.sys.net.host_hints())
|
||||
|
||||
return
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function progressbar(v, m)
|
||||
{
|
||||
var vn = parseInt(v) || 0;
|
||||
var mn = parseInt(m) || 100;
|
||||
var pc = Math.floor((100 / mn) * vn);
|
||||
|
||||
return String.format(
|
||||
'<div style="width:200px; position:relative; border:1px solid #999999">' +
|
||||
'<div style="background-color:#CCCCCC; width:%d%%; height:15px">' +
|
||||
'<div style="position:absolute; left:0; top:0; text-align:center; width:100%%; color:#000000">' +
|
||||
'<small>%s / %s (%d%%)</small>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>', pc, v, m, pc
|
||||
);
|
||||
}
|
||||
|
||||
function wifirate(bss, rx) {
|
||||
var p = rx ? 'rx_' : 'tx_',
|
||||
s = '%.1f <%:Mbit/s%>, %d<%:MHz%>'
|
||||
.format(bss[p+'rate'] / 1000, bss[p+'mhz']),
|
||||
ht = bss[p+'ht'], vht = bss[p+'vht'],
|
||||
mhz = bss[p+'mhz'], nss = bss[p+'nss'],
|
||||
mcs = bss[p+'mcs'], sgi = bss[p+'short_gi'],
|
||||
he = bss[p+'he'], he_gi = bss[p+'he_gi'],
|
||||
he_dcm = bss[p+'he_dcm'];
|
||||
|
||||
if (ht || vht) {
|
||||
if (vht) s += ', VHT-MCS %d'.format(mcs);
|
||||
if (nss) s += ', VHT-NSS %d'.format(nss);
|
||||
if (ht) s += ', MCS %s'.format(mcs);
|
||||
if (sgi) s += ', <%:Short GI%>';
|
||||
}
|
||||
|
||||
if (he) {
|
||||
s += ', HE-MCS %d'.format(mcs);
|
||||
if (nss) s += ', HE-NSS %d'.format(nss);
|
||||
if (he_gi) s += ', HE-GI %d'.format(he_gi);
|
||||
if (he_dcm) s += ', HE-DCM %d'.format(he_dcm);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function duid2mac(duid) {
|
||||
// DUID-LLT / Ethernet
|
||||
if (duid.length === 28 && duid.substr(0, 8) === '00010001')
|
||||
return duid.substr(16).replace(/(..)(?=..)/g, '$1:').toUpperCase();
|
||||
|
||||
// DUID-LL / Ethernet
|
||||
if (duid.length === 20 && duid.substr(0, 8) === '00030001')
|
||||
return duid.substr(8).replace(/(..)(?=..)/g, '$1:').toUpperCase();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var npoll = 1;
|
||||
var hosts = <%=luci.http.write_json(luci.sys.net.host_hints())%>;
|
||||
|
||||
function updateHosts() {
|
||||
XHR.get('<%=REQUEST_URI%>', { hosts: 1 }, function(x, data) {
|
||||
hosts = data;
|
||||
});
|
||||
}
|
||||
|
||||
XHR.poll(5, '<%=REQUEST_URI%>', { status: 1 },
|
||||
function(x, info)
|
||||
{
|
||||
if (!(npoll++ % 5))
|
||||
updateHosts();
|
||||
|
||||
var si = document.getElementById('wan4_i');
|
||||
var ss = document.getElementById('wan4_s');
|
||||
var ifc = info.wan;
|
||||
|
||||
if (ifc && ifc.ifname && ifc.proto != 'none')
|
||||
{
|
||||
var s = String.format(
|
||||
'<strong><%:Type%>: </strong>%s<br />' +
|
||||
'<strong><%:Address%>: </strong>%s<br />' +
|
||||
'<strong><%:Netmask%>: </strong>%s<br />' +
|
||||
'<strong><%:Gateway%>: </strong>%s<br />',
|
||||
ifc.proto,
|
||||
(ifc.ipaddr) ? ifc.ipaddr : '0.0.0.0',
|
||||
(ifc.netmask && ifc.netmask != ifc.ipaddr) ? ifc.netmask : '255.255.255.255',
|
||||
(ifc.gwaddr) ? ifc.gwaddr : '0.0.0.0'
|
||||
);
|
||||
|
||||
for (var i = 0; i < ifc.dns.length; i++)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:DNS%> %d: </strong>%s<br />',
|
||||
i + 1, ifc.dns[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.expires > -1)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Expires%>: </strong>%t<br />',
|
||||
ifc.expires
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.uptime > 0)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Connected%>: </strong>%t<br />',
|
||||
ifc.uptime
|
||||
);
|
||||
}
|
||||
|
||||
ss.innerHTML = String.format('<small>%s</small>', s);
|
||||
si.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/ethernet.png" />' +
|
||||
'<br /><small><a href="%s">%s</a></small>',
|
||||
ifc.link, ifc.ifname
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
si.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
|
||||
ss.innerHTML = '<em><%:Not connected%></em>';
|
||||
}
|
||||
|
||||
<% if has_ipv6 then %>
|
||||
var si6 = document.getElementById('wan6_i');
|
||||
var ss6 = document.getElementById('wan6_s');
|
||||
var ifc6 = info.wan6;
|
||||
|
||||
if (ifc6 && ifc6.ifname && ifc6.proto != 'none')
|
||||
{
|
||||
var s = String.format(
|
||||
'<strong><%:Type%>: </strong>%s%s<br />',
|
||||
ifc6.proto, (ifc6.ip6prefix) ? '-pd' : ''
|
||||
);
|
||||
|
||||
if (!ifc6.ip6prefix)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Address%>: </strong>%s<br />',
|
||||
(ifc6.ip6addr) ? ifc6.ip6addr : '::'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Prefix Delegated%>: </strong>%s<br />',
|
||||
ifc6.ip6prefix
|
||||
);
|
||||
if (ifc6.ip6addr)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Address%>: </strong>%s<br />',
|
||||
ifc6.ip6addr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
s += String.format(
|
||||
'<strong><%:Gateway%>: </strong>%s<br />',
|
||||
(ifc6.gw6addr) ? ifc6.gw6addr : '::'
|
||||
);
|
||||
|
||||
for (var i = 0; i < ifc6.dns.length; i++)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:DNS%> %d: </strong>%s<br />',
|
||||
i + 1, ifc6.dns[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc6.uptime > 0)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Connected%>: </strong>%t<br />',
|
||||
ifc6.uptime
|
||||
);
|
||||
}
|
||||
|
||||
ss6.innerHTML = String.format('<small>%s</small>', s);
|
||||
si6.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/ethernet.png" />' +
|
||||
'<br /><small><a href="%s">%s</a></small>',
|
||||
ifc6.link, ifc6.ifname
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
si6.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
|
||||
ss6.innerHTML = '<em><%:Not connected%></em>';
|
||||
}
|
||||
<% end %>
|
||||
|
||||
<% if has_dsl then %>
|
||||
var dsl_i = document.getElementById('dsl_i');
|
||||
var dsl_s = document.getElementById('dsl_s');
|
||||
|
||||
var s = String.format(
|
||||
'<strong><%:Status%>: </strong>%s<br />' +
|
||||
'<strong><%:Line State%>: </strong>%s [0x%x]<br />' +
|
||||
'<strong><%:Line Mode%>: </strong>%s<br />' +
|
||||
'<strong><%:Annex%>: </strong>%s<br />' +
|
||||
'<strong><%:Profile%>: </strong>%s<br />' +
|
||||
'<strong><%:Data Rate%>: </strong>%s/s / %s/s<br />' +
|
||||
'<strong><%:Max. Attainable Data Rate (ATTNDR)%>: </strong>%s/s / %s/s<br />' +
|
||||
'<strong><%:Latency%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Line Attenuation (LATN)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Signal Attenuation (SATN)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Noise Margin (SNR)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Aggregate Transmit Power(ACTATP)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Forward Error Correction Seconds (FECS)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Errored seconds (ES)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Severely Errored Seconds (SES)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Loss of Signal Seconds (LOSS)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Unavailable Seconds (UAS)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Header Error Code Errors (HEC)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Non Pre-emtive CRC errors (CRC_P)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Pre-emtive CRC errors (CRCP_P)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Line Uptime%>: </strong>%s<br />' +
|
||||
'<strong><%:ATU-C System Vendor ID%>: </strong>%s<br />' +
|
||||
'<strong><%:Power Management Mode%>: </strong>%s<br />',
|
||||
info.dsl.line_state, info.dsl.line_state_detail,
|
||||
info.dsl.line_state_num,
|
||||
info.dsl.line_mode_s,
|
||||
info.dsl.annex_s,
|
||||
info.dsl.profile_s,
|
||||
info.dsl.data_rate_down_s, info.dsl.data_rate_up_s,
|
||||
info.dsl.max_data_rate_down_s, info.dsl.max_data_rate_up_s,
|
||||
info.dsl.latency_num_down, info.dsl.latency_num_up,
|
||||
info.dsl.line_attenuation_down, info.dsl.line_attenuation_up,
|
||||
info.dsl.signal_attenuation_down, info.dsl.signal_attenuation_up,
|
||||
info.dsl.noise_margin_down, info.dsl.noise_margin_up,
|
||||
info.dsl.actatp_down, info.dsl.actatp_up,
|
||||
info.dsl.errors_fec_near, info.dsl.errors_fec_far,
|
||||
info.dsl.errors_es_near, info.dsl.errors_es_far,
|
||||
info.dsl.errors_ses_near, info.dsl.errors_ses_far,
|
||||
info.dsl.errors_loss_near, info.dsl.errors_loss_far,
|
||||
info.dsl.errors_uas_near, info.dsl.errors_uas_far,
|
||||
info.dsl.errors_hec_near, info.dsl.errors_hec_far,
|
||||
info.dsl.errors_crc_p_near, info.dsl.errors_crc_p_far,
|
||||
info.dsl.errors_crcp_p_near, info.dsl.errors_crcp_p_far,
|
||||
info.dsl.line_uptime_s,
|
||||
info.dsl.atuc_vendor_id,
|
||||
info.dsl.power_mode_s
|
||||
);
|
||||
|
||||
dsl_s.innerHTML = String.format('<small>%s</small>', s);
|
||||
dsl_i.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/ethernet.png" />' +
|
||||
'<br /><small>DSL</small>'
|
||||
);
|
||||
<% end %>
|
||||
|
||||
<% if has_dhcp then %>
|
||||
var ls = document.getElementById('lease_status_table');
|
||||
if (ls)
|
||||
{
|
||||
/* clear all rows */
|
||||
while( ls.rows.length > 1 )
|
||||
ls.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
for( var i = 0; i < info.leases.length; i++ )
|
||||
{
|
||||
var timestr;
|
||||
|
||||
if (info.leases[i].expires === false)
|
||||
timestr = '<em><%:unlimited%></em>';
|
||||
else if (info.leases[i].expires <= 0)
|
||||
timestr = '<em><%:expired%></em>';
|
||||
else
|
||||
timestr = String.format('%t', info.leases[i].expires);
|
||||
|
||||
var tr = ls.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
|
||||
|
||||
tr.insertCell(-1).innerHTML = info.leases[i].hostname ? info.leases[i].hostname : '?';
|
||||
tr.insertCell(-1).innerHTML = info.leases[i].ipaddr;
|
||||
tr.insertCell(-1).innerHTML = info.leases[i].macaddr;
|
||||
tr.insertCell(-1).innerHTML = timestr;
|
||||
}
|
||||
|
||||
if( ls.rows.length == 1 )
|
||||
{
|
||||
var tr = ls.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 4;
|
||||
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
|
||||
}
|
||||
}
|
||||
|
||||
var ls6 = document.getElementById('lease6_status_table');
|
||||
if (ls6 && info.leases6)
|
||||
{
|
||||
ls6.parentNode.style.display = 'block';
|
||||
|
||||
/* clear all rows */
|
||||
while( ls6.rows.length > 1 )
|
||||
ls6.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
for( var i = 0; i < info.leases6.length; i++ )
|
||||
{
|
||||
var timestr;
|
||||
|
||||
if (info.leases6[i].expires === false)
|
||||
timestr = '<em><%:unlimited%></em>';
|
||||
else if (info.leases6[i].expires <= 0)
|
||||
timestr = '<em><%:expired%></em>';
|
||||
else
|
||||
timestr = String.format('%t', info.leases6[i].expires);
|
||||
|
||||
var tr = ls6.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
|
||||
|
||||
var host = hosts[duid2mac(info.leases6[i].duid)];
|
||||
if (!info.leases6[i].hostname)
|
||||
tr.insertCell(-1).innerHTML =
|
||||
(host && (host.name || host.ipv4 || host.ipv6))
|
||||
? '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space: nowrap">? (%h)</div>'.format(host.name || host.ipv4 || host.ipv6)
|
||||
: '?';
|
||||
else
|
||||
tr.insertCell(-1).innerHTML =
|
||||
(host && host.name && info.leases6[i].hostname != host.name)
|
||||
? '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space: nowrap">%h (%h)</div>'.format(info.leases6[i].hostname, host.name)
|
||||
: info.leases6[i].hostname;
|
||||
|
||||
tr.insertCell(-1).innerHTML = info.leases6[i].ip6addr;
|
||||
tr.insertCell(-1).innerHTML = info.leases6[i].duid;
|
||||
tr.insertCell(-1).innerHTML = timestr;
|
||||
}
|
||||
|
||||
if( ls6.rows.length == 1 )
|
||||
{
|
||||
var tr = ls6.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 4;
|
||||
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
|
||||
}
|
||||
}
|
||||
<% end %>
|
||||
|
||||
<% if has_wifi then %>
|
||||
var assoclist = [ ];
|
||||
|
||||
var ws = document.getElementById('wifi_status_table');
|
||||
if (ws)
|
||||
{
|
||||
var wsbody = ws.rows[0].parentNode;
|
||||
while (ws.rows.length > 0)
|
||||
wsbody.deleteRow(0);
|
||||
|
||||
for (var didx = 0; didx < info.wifinets.length; didx++)
|
||||
{
|
||||
var dev = info.wifinets[didx];
|
||||
|
||||
var tr = wsbody.insertRow(-1);
|
||||
var td;
|
||||
|
||||
td = tr.insertCell(-1);
|
||||
td.width = "33%";
|
||||
td.innerHTML = dev.name;
|
||||
td.style.verticalAlign = "top";
|
||||
|
||||
td = tr.insertCell(-1);
|
||||
|
||||
var s = '';
|
||||
|
||||
for (var nidx = 0; nidx < dev.networks.length; nidx++)
|
||||
{
|
||||
var net = dev.networks[nidx];
|
||||
var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel && !net.disabled);
|
||||
|
||||
var icon;
|
||||
if (!is_assoc)
|
||||
icon = "<%=resource%>/icons/signal-none.png";
|
||||
else if (net.quality == 0)
|
||||
icon = "<%=resource%>/icons/signal-0.png";
|
||||
else if (net.quality < 25)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (net.quality < 50)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (net.quality < 75)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
s += String.format(
|
||||
'<table><tr><td style="text-align:center; width:32px; padding:3px">' +
|
||||
'<img src="%s" title="<%:Signal%>: %d dBm / <%:Noise%>: %d dBm" />' +
|
||||
'<br /><small>%d%%</small>' +
|
||||
'</td><td style="text-align:left; padding:3px"><small>' +
|
||||
'<strong><%:SSID%>:</strong> <a href="%s">%h</a><br />' +
|
||||
'<strong><%:Mode%>:</strong> %s<br />' +
|
||||
'<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>)<br />' +
|
||||
'<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%><br />',
|
||||
icon, net.signal, net.noise,
|
||||
net.quality,
|
||||
net.link, net.ssid || '?',
|
||||
net.mode,
|
||||
net.channel, net.frequency,
|
||||
net.bitrate || '?'
|
||||
);
|
||||
|
||||
if (is_assoc)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:BSSID%>:</strong> %s<br />' +
|
||||
'<strong><%:Encryption%>:</strong> %s',
|
||||
net.bssid || '?',
|
||||
net.encryption
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
s += '<em><%:Wireless is disabled or not associated%></em>';
|
||||
}
|
||||
|
||||
s += '</small></td></tr></table>';
|
||||
|
||||
for (var bssid in net.assoclist)
|
||||
{
|
||||
var bss = net.assoclist[bssid];
|
||||
|
||||
bss.bssid = bssid;
|
||||
bss.link = net.link;
|
||||
bss.name = net.name;
|
||||
bss.ifname = net.ifname;
|
||||
bss.radio = dev.name;
|
||||
|
||||
assoclist.push(bss);
|
||||
}
|
||||
}
|
||||
|
||||
if (!s)
|
||||
s = '<em><%:No information available%></em>';
|
||||
|
||||
td.innerHTML = s;
|
||||
}
|
||||
}
|
||||
|
||||
var ac = document.getElementById('wifi_assoc_table');
|
||||
if (ac)
|
||||
{
|
||||
/* clear all rows */
|
||||
while( ac.rows.length > 1 )
|
||||
ac.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
assoclist.sort(function(a, b) {
|
||||
return (a.name == b.name)
|
||||
? (a.bssid < b.bssid)
|
||||
: (a.name > b.name )
|
||||
;
|
||||
});
|
||||
|
||||
for( var i = 0; i < assoclist.length; i++ )
|
||||
{
|
||||
var tr = ac.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
|
||||
|
||||
var icon;
|
||||
var q = (-1 * (assoclist[i].noise - assoclist[i].signal)) / 5;
|
||||
if (q < 1)
|
||||
icon = "<%=resource%>/icons/signal-0.png";
|
||||
else if (q < 2)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (q < 3)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (q < 4)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> %h</span>',
|
||||
assoclist[i].radio, assoclist[i].ifname
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<a href="%s">%s</a>',
|
||||
assoclist[i].link,
|
||||
'%h'.format(assoclist[i].name).nobr()
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = assoclist[i].bssid;
|
||||
|
||||
var host = hosts[assoclist[i].bssid];
|
||||
if (host)
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
|
||||
((host.name && (host.ipv4 || host.ipv6))
|
||||
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
|
||||
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
|
||||
);
|
||||
else
|
||||
tr.insertCell(-1).innerHTML = '?';
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>',
|
||||
assoclist[i].signal, assoclist[i].noise, assoclist[i].signal - assoclist[i].noise,
|
||||
icon,
|
||||
assoclist[i].signal, assoclist[i].noise
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = wifirate(assoclist[i], true).nobr() + '<br />' + wifirate(assoclist[i], false).nobr();
|
||||
}
|
||||
|
||||
if (ac.rows.length == 1)
|
||||
{
|
||||
var tr = ac.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 7;
|
||||
td.innerHTML = '<br /><em><%:No information available%></em>';
|
||||
}
|
||||
}
|
||||
<% end %>
|
||||
|
||||
var e;
|
||||
|
||||
if (e = document.getElementById('ethinfo')) {
|
||||
var ports = eval('(' + info.ethinfo + ')');
|
||||
var tmp = "";
|
||||
for (var i in ports)
|
||||
{
|
||||
tmp = tmp + String.format(
|
||||
'<td style="text-align:center"><span style="line-height:25px">%s</span><br /><small><img src="<%=resource%>/icons/%s" /><br />%s<br />%s</small></td>', ports[i].name,
|
||||
ports[i].status ? 'port_up.png' : 'port_down.png',
|
||||
ports[i].speed,
|
||||
ports[i].duplex ? '<%:full-duplex%>' : '<%:half-duplex%>');
|
||||
};
|
||||
e.innerHTML = "<tr>" + tmp + "</tr>";
|
||||
}
|
||||
|
||||
if (e = document.getElementById('localtime'))
|
||||
e.innerHTML = info.localtime;
|
||||
|
||||
if (e = document.getElementById('uptime'))
|
||||
e.innerHTML = String.format('%t', info.uptime);
|
||||
|
||||
if (e = document.getElementById('userinfo'))
|
||||
e.innerHTML = info.userinfo;
|
||||
|
||||
if (e = document.getElementById('cpuusage'))
|
||||
e.innerHTML = info.cpuusage;
|
||||
|
||||
if (e = document.getElementById('cpuinfo'))
|
||||
e.innerHTML = info.cpuinfo;
|
||||
|
||||
if (e = document.getElementById('loadavg'))
|
||||
e.innerHTML = String.format(
|
||||
'%.02f, %.02f, %.02f',
|
||||
info.loadavg[0] / 65535.0,
|
||||
info.loadavg[1] / 65535.0,
|
||||
info.loadavg[2] / 65535.0
|
||||
);
|
||||
|
||||
if (e = document.getElementById('memtotal'))
|
||||
e.innerHTML = progressbar(
|
||||
Math.floor(((info.memory.free + info.memory.buffered) / 1048576) + (info.memcached / 1024)) + " <%:MB%>",
|
||||
Math.floor(info.memory.total / 1048576) + " <%:MB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('membuff'))
|
||||
e.innerHTML = progressbar(
|
||||
Math.floor(info.memory.buffered / 1048576) + " <%:MB%>",
|
||||
Math.floor(info.memory.total / 1048576) + " <%:MB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('swaptotal'))
|
||||
e.innerHTML = progressbar(
|
||||
Math.floor(info.swap.free / 1048576) + " <%:MB%>",
|
||||
Math.floor(info.swap.total / 1048576) + " <%:MB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('swapfree'))
|
||||
e.innerHTML = progressbar(
|
||||
Math.floor(info.swap.free / 1048576) + " <%:MB%>",
|
||||
Math.floor(info.swap.total / 1048576) + " <%:MB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('conns'))
|
||||
e.innerHTML = progressbar(info.conncount, info.connmax);
|
||||
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Status%></h2>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:System%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%"><%:Hostname%></td><td><%=luci.sys.hostname() or "?"%></td></tr>
|
||||
<tr><td width="33%"><%:Model%></td><td><%=pcdata(boardinfo.model or "?")%> <%=luci.sys.exec("cat /etc/bench.log") or ""%></td></tr>
|
||||
<tr><td width="33%"><%:Architecture%></td><td id="cpuinfo">-</td></tr>
|
||||
<tr><td width="33%"><%:Firmware Version%></td><td>
|
||||
<%=pcdata(ver.distname)%> <%=pcdata(ver.distversion)%> /
|
||||
<%=pcdata(ver.luciname)%> (<%=pcdata(ver.luciversion)%>)
|
||||
</td></tr>
|
||||
<tr><td width="33%"><%:Kernel Version%></td><td><%=luci.sys.exec("uname -r | awk -F '-' '{print $1}'") or "?"%></td></tr>
|
||||
<tr><td width="33%"><%:Local Time%></td><td id="localtime">-</td></tr>
|
||||
<tr><td width="33%"><%:Uptime%></td><td id="uptime">-</td></tr>
|
||||
<tr><td width="33%"><%:Load Average%></td><td id="loadavg">-</td></tr>
|
||||
<tr><td width="33%"><%:CPU usage%></td><td id="cpuusage">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Memory%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%"><%:Total Available%></td><td id="memtotal">-</td></tr>
|
||||
<tr><td width="33%"><%:Buffered%></td><td id="membuff">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<% if swapinfo.total > 0 then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Swap%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%"><%:Total Available%></td><td id="swaptotal">-</td></tr>
|
||||
<tr><td width="33%"><%:Free%></td><td id="swapfree">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<% if not has_switch then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Interfaces%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10" id="ethinfo">
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Network%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%" style="vertical-align:top"><%:IPv4 WAN Status%></td><td>
|
||||
<table><tr>
|
||||
<td id="wan4_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
|
||||
<td id="wan4_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
<% if has_ipv6 then %>
|
||||
<tr><td width="33%" style="vertical-align:top"><%:IPv6 WAN Status%></td><td>
|
||||
<table><tr>
|
||||
<td id="wan6_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
|
||||
<td id="wan6_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
<% end %>
|
||||
<tr><td width="33%"><%:Online Users%></td><td id="userinfo">0</td></tr>
|
||||
<tr><td width="33%"><%:Active Connections%></td><td id="conns">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<% if has_dhcp then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:DHCP Leases%></legend>
|
||||
|
||||
<table class="cbi-section-table" id="lease_status_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Hostname%></th>
|
||||
<th class="cbi-section-table-cell"><%:IPv4-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<% if has_ipv6 then %>
|
||||
<fieldset class="cbi-section" style="display:none">
|
||||
<legend><%:DHCPv6 Leases%></legend>
|
||||
|
||||
<table class="cbi-section-table" id="lease6_status_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Host%></th>
|
||||
<th class="cbi-section-table-cell"><%:IPv6-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:DUID%></th>
|
||||
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if has_dsl then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:DSL%></legend>
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%" style="vertical-align:top"><%:DSL Status%></td><td>
|
||||
<table><tr>
|
||||
<td id="dsl_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
|
||||
<td id="dsl_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<% if has_wifi then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Wireless%></legend>
|
||||
|
||||
<table id="wifi_status_table" width="100%" cellspacing="10">
|
||||
<tr><td><em><%:Collecting data...%></em></td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<%+footer%>
|
||||
@ -1,45 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
cpu_arch="$(cat "/proc/cpuinfo" | grep "model name" | sed -n "1p" | awk -F ': ' '{print $2}')"
|
||||
[ -z "${cpu_arch}" ] && cpu_arch="ARMv8 Processor"
|
||||
cpu_cores="$(cat "/proc/cpuinfo" | grep "processor" | wc -l)"
|
||||
|
||||
if grep -q "bcm27xx" "/etc/openwrt_release"; then
|
||||
cpu_freq="$(expr $(vcgencmd measure_clock arm | awk -F '=' '{print $2}') / 1000000)Mhz"
|
||||
elif grep -q "bcm53xx" "/etc/openwrt_release"; then
|
||||
cpu_freq="$(nvram get clkfreq | awk -F ',' '{print $1}')MHz"
|
||||
elif grep -q "mvebu" "/etc/openwrt_release"; then
|
||||
cpu_freq="$(cat "/proc/cpuinfo" | grep "BogoMIPS" | sed -n "1p" | awk -F ': ' '{print $2}')MHz"
|
||||
elif grep -q "filogic" "/etc/openwrt_release"; then
|
||||
[ -f "/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq" ] && big_cpu_freq="$(expr $(cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq) / 1000)MHz"
|
||||
elif grep -q "rockchip" "/etc/openwrt_release"; then
|
||||
cpu_freq="$(expr $(cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq) / 1000)MHz"
|
||||
big_cpu_freq="$(expr $(cat /sys/devices/system/cpu/cpufreq/policy4/cpuinfo_cur_freq 2>"/dev/null") / 1000 2>"/dev/null")"
|
||||
[ -n "${big_cpu_freq}" ] && big_cpu_freq="${big_cpu_freq}MHz "
|
||||
else
|
||||
cpu_freq="$(expr $(cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq) / 1000)MHz"
|
||||
fi
|
||||
|
||||
if grep -q "ipq" "/etc/openwrt_release"; then
|
||||
if grep -q "ipq40xx" "/etc/openwrt_release"; then
|
||||
sys_temp="$(awk '{ printf("%.1f°C ", $0 / 1000) }' /sys/class/ieee80211/phy*/device/hwmon/hwmon*/temp1_input)"
|
||||
else
|
||||
sys_temp="$(awk '{ printf("%.1f°C ", $0 / 1000) }' /sys/class/thermal/thermal_zone0/temp)"
|
||||
fi
|
||||
echo -n "${cpu_arch} x ${cpu_cores} (${cpu_freq}, ${sys_temp})"
|
||||
else
|
||||
if grep -q "bcm27xx" "/etc/openwrt_release"; then
|
||||
cpu_temp="$(vcgencmd measure_temp | awk -F '=' '{print $2}' | awk -F "'" '{print $1}')°C"
|
||||
else
|
||||
cpu_temp="$(awk "BEGIN{printf (\"%.1f\n\",$(cat /sys/class/thermal/thermal_zone0/temp)/1000) }")°C"
|
||||
fi
|
||||
if grep -q "filogic" "/etc/openwrt_release"; then
|
||||
if [ -n "${big_cpu_freq}" ] ; then
|
||||
echo -n "${cpu_arch} x ${cpu_cores} (${big_cpu_freq}, ${cpu_temp})"
|
||||
else
|
||||
echo -n "${cpu_arch} x ${cpu_cores} (${cpu_temp})"
|
||||
fi
|
||||
else
|
||||
echo -n "${cpu_arch} x ${cpu_cores} (${big_cpu_freq}${cpu_freq}, ${cpu_temp})"
|
||||
fi
|
||||
fi
|
||||
@ -1,45 +0,0 @@
|
||||
#!/usr/bin/lua
|
||||
-- Copyright (C) 2022 ImmortalWrt.org
|
||||
|
||||
local util = require "luci.util"
|
||||
local jsonc = require "luci.jsonc"
|
||||
|
||||
local eth_info = {}
|
||||
local ifname, stat
|
||||
|
||||
for ifname, stat in pairs(util.ubus("network.device", "status")) do
|
||||
while true do
|
||||
if (ifname:match("^(br-.+)$")) == ifname then
|
||||
break
|
||||
else
|
||||
local status, speed, duplex
|
||||
|
||||
if(stat.speed ~= nil) then
|
||||
status = stat.carrier and 1 or 0
|
||||
|
||||
if stat.speed:sub(1, 1) == "-" then
|
||||
speed = " - "
|
||||
else
|
||||
speed = stat.speed:sub(1, -2) .. "Mb/s"
|
||||
end
|
||||
|
||||
if stat.carrier and stat.speed:sub(-1) == "F" then
|
||||
duplex = 1
|
||||
else
|
||||
duplex = 0
|
||||
end
|
||||
|
||||
eth_info[#eth_info+1] = { name = ifname, status = status,
|
||||
speed = speed, duplex = duplex }
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(eth_info,
|
||||
function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
||||
print(jsonc.stringify(eth_info))
|
||||
@ -1,40 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. /etc/openwrt_release
|
||||
|
||||
IEEE_PATH="/sys/class/ieee80211"
|
||||
THERMAL_PATH="/sys/class/thermal"
|
||||
|
||||
case "$DISTRIB_TARGET" in
|
||||
ipq40xx/*|ipq806x/*)
|
||||
wifi_temp="$(awk '{printf("%.1f°C ", $0 / 1000)}' "$IEEE_PATH"/phy*/device/hwmon/hwmon*/temp1_input 2>"/dev/null" | awk '$1=$1')"
|
||||
;;
|
||||
mediatek/mt7622)
|
||||
wifi_temp="$(awk '{printf("%.1f°C ", $0 / 1000)}' "$IEEE_PATH"/wl*/hwmon*/temp1_input 2>"/dev/null" | awk '$1=$1')"
|
||||
;;
|
||||
*)
|
||||
wifi_temp="$(awk '{printf("%.1f°C ", $0 / 1000)}' "$IEEE_PATH"/phy*/hwmon*/temp1_input 2>"/dev/null" | awk '$1=$1')"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$DISTRIB_TARGET" in
|
||||
ipq40xx/*)
|
||||
if [ -e "$IEEE_PATH/phy0/hwmon0/temp1_input" ]; then
|
||||
mt76_temp="$(awk -F ': ' '{print $2}' "$IEEE_PATH/phy0/hwmon0/temp1_input" 2>"/dev/null")°C"
|
||||
fi
|
||||
[ -z "$mt76_temp" ] || wifi_temp="${wifi_temp:+$wifi_temp }$mt76_temp"
|
||||
;;
|
||||
*)
|
||||
cpu_temp="$(awk '{printf("%.1f°C", $0 / 1000)}' "$THERMAL_PATH/thermal_zone0/temp" 2>"/dev/null")"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -n "$cpu_temp" ] && [ -z "$wifi_temp" ]; then
|
||||
echo -n "CPU: $cpu_temp"
|
||||
elif [ -z "$cpu_temp" ] && [ -n "$wifi_temp" ]; then
|
||||
echo -n "WiFi: $wifi_temp"
|
||||
elif [ -n "$cpu_temp" ] && [ -n "$wifi_temp" ]; then
|
||||
echo -n "CPU: $cpu_temp, WiFi: $wifi_temp"
|
||||
else
|
||||
echo -n "No temperature info"
|
||||
fi
|
||||
@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
NSS_PATH="/sys/kernel/debug/qca-nss-drv/stats"
|
||||
|
||||
cpu_usage="$(busybox top -n1 | awk '/^CPU/ {printf("%d%", 100 - $8)}')"
|
||||
|
||||
[ ! -d "$NSS_PATH" ] || \
|
||||
npu_usage="$(grep '%' "$NSS_PATH"/cpu_load_ubi | awk -F ' ' '{print $2}')"
|
||||
|
||||
if [ -d "$NSS_PATH" ]; then
|
||||
echo -n "CPU: ${cpu_usage}, NPU: ${npu_usage}"
|
||||
else
|
||||
echo -n "CPU: ${cpu_usage}"
|
||||
fi
|
||||
@ -1,20 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2025 lean <coolsnowwolf@gmail.com>
|
||||
|
||||
START=99
|
||||
|
||||
start()
|
||||
{
|
||||
a=$(cat /proc/cpuinfo | grep 'Model Name' | cut -f2 -d: | head -n 1)
|
||||
b=$(echo -n ' : ')
|
||||
c=$(cat /proc/cpuinfo | grep 'core' | sort -u | wc -l)
|
||||
d=$(echo -n 'C')
|
||||
e=$(cat /proc/cpuinfo | grep 'global_id' | sort -u | wc -l)
|
||||
f=$(echo -n 'T ')
|
||||
g=$(cat /proc/cpuinfo | grep 'CPU Family' | cut -f2 -d: | head -n 1)
|
||||
|
||||
h=${g}' - '${a}${b}${c}${d}${e}${f}
|
||||
|
||||
mkdir -p /tmp/sysinfo
|
||||
echo $h > /tmp/sysinfo/model
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
MHz=`grep 'MHz' /proc/cpuinfo | cut -c13- |sed -n '1p'`
|
||||
|
||||
echo "$MHz MHz"
|
||||
@ -1,45 +0,0 @@
|
||||
#!/usr/bin/lua
|
||||
-- Copyright (C) 2022 ImmortalWrt.org
|
||||
|
||||
local util = require "luci.util"
|
||||
local jsonc = require "luci.jsonc"
|
||||
|
||||
local eth_info = {}
|
||||
local ifname, stat
|
||||
|
||||
for ifname, stat in pairs(util.ubus("network.device", "status")) do
|
||||
while true do
|
||||
if (ifname:match("^(br-.+)$")) == ifname then
|
||||
break
|
||||
else
|
||||
local status, speed, duplex
|
||||
|
||||
if(stat.speed ~= nil) then
|
||||
status = stat.carrier and 1 or 0
|
||||
|
||||
if stat.speed:sub(1, 1) == "-" then
|
||||
speed = " - "
|
||||
else
|
||||
speed = stat.speed:sub(1, -2) .. "Mb/s"
|
||||
end
|
||||
|
||||
if stat.carrier and stat.speed:sub(-1) == "F" then
|
||||
duplex = 1
|
||||
else
|
||||
duplex = 0
|
||||
end
|
||||
|
||||
eth_info[#eth_info+1] = { name = ifname, status = status,
|
||||
speed = speed, duplex = duplex }
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(eth_info,
|
||||
function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
||||
print(jsonc.stringify(eth_info))
|
||||
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
TEMP=`awk '{printf("%.1f°C", $0 / 1000)}' "/sys/class/thermal/thermal_zone0/temp" 2>"/dev/null"`
|
||||
|
||||
echo "$TEMP "
|
||||
@ -1,10 +0,0 @@
|
||||
{
|
||||
"luci-mod-status-autocore": {
|
||||
"description": "Grant access to autocore",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"luci": [ "getCPUInfo", "getCPUUsage", "getTempInfo" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2017 lean <coolsnowwolf@gmail.com>
|
||||
|
||||
START=99
|
||||
|
||||
start()
|
||||
{
|
||||
rfc=4096
|
||||
cc=$(grep -c processor /proc/cpuinfo)
|
||||
rsfe=$(echo $cc*$rfc | bc)
|
||||
sysctl -w net.core.rps_sock_flow_entries=$rsfe >/dev/null
|
||||
for fileRps in $(ls /sys/class/net/eth*/queues/rx-*/rps_cpus)
|
||||
do
|
||||
echo $cc > $fileRps
|
||||
done
|
||||
|
||||
for fileRfc in $(ls /sys/class/net/eth*/queues/rx-*/rps_flow_cnt)
|
||||
do
|
||||
echo $rfc > $fileRfc
|
||||
done
|
||||
|
||||
uci set network.@globals[0].packet_steering=1
|
||||
uci commit network
|
||||
|
||||
all_pcis=`lspci | grep -i 'eth' | grep -i 'x550' | cut -d ' ' -f 1`
|
||||
all_ifs=`cat /proc/net/dev | grep -i 'eth' | cut -d : -f 1 | sed 's/^[ \t]*//g'`
|
||||
|
||||
for ifname in ${all_ifs}
|
||||
do
|
||||
if_pci=`ethtool -i ${ifname} | grep -i 'bus-info' | cut -d : -f 3-`
|
||||
if [[ "$all_pcis" =~ "$if_pci" ]]
|
||||
then
|
||||
ethtool -s ${ifname} advertise 0x1800000001028
|
||||
fi
|
||||
done
|
||||
|
||||
a=$(ip address | grep ^[0-9] | awk -F: '{print $2}' | sed "s/ //g" | grep '^[e]' | grep -v "@" | grep -v "\.")
|
||||
b=$(echo "$a" | wc -l)
|
||||
for i in $(seq 1 $b)
|
||||
do
|
||||
c=$(echo "$a" | sed -n ${i}p)
|
||||
ethtool -K $c rx-checksum on >/dev/null 2>&1
|
||||
ethtool -K $c tx-checksum-ip-generic on >/dev/null 2>&1 || (
|
||||
ethtool -K $c tx-checksum-ipv4 on >/dev/null 2>&1
|
||||
ethtool -K $c tx-checksum-ipv6 on >/dev/null 2>&1)
|
||||
ethtool -K $c tx-scatter-gather on >/dev/null 2>&1
|
||||
ethtool -K $c tso on >/dev/null 2>&1
|
||||
done
|
||||
|
||||
[ -f /etc/index.htm ] && mv /etc/index.htm /usr/lib/lua/luci/view/admin_status/index.htm
|
||||
}
|
||||
@ -1,864 +0,0 @@
|
||||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local fs = require "nixio.fs"
|
||||
local util = require "luci.util"
|
||||
local stat = require "luci.tools.status"
|
||||
local ver = require "luci.version"
|
||||
|
||||
local has_ipv6 = fs.access("/usr/sbin/ip6tables")
|
||||
local has_dhcp = fs.access("/etc/config/dhcp")
|
||||
local has_wifi = ((fs.stat("/etc/config/wireless", "size") or 0) > 0)
|
||||
|
||||
local sysinfo = luci.util.ubus("system", "info") or { }
|
||||
local boardinfo = luci.util.ubus("system", "board") or { }
|
||||
local unameinfo = nixio.uname() or { }
|
||||
|
||||
local meminfo = sysinfo.memory or {
|
||||
total = 0,
|
||||
free = 0,
|
||||
buffered = 0,
|
||||
shared = 0
|
||||
}
|
||||
|
||||
local mem_cached = luci.sys.exec("sed -e '/^Cached: /!d; s#Cached: *##; s# kB##g' /proc/meminfo")
|
||||
|
||||
local swapinfo = sysinfo.swap or {
|
||||
total = 0,
|
||||
free = 0
|
||||
}
|
||||
|
||||
local has_dsl = fs.access("/etc/init.d/dsl_control")
|
||||
|
||||
if luci.http.formvalue("status") == "1" then
|
||||
local ntm = require "luci.model.network".init()
|
||||
local wan = ntm:get_wannet()
|
||||
local wan6 = ntm:get_wan6net()
|
||||
|
||||
local conn_count = tonumber(
|
||||
fs.readfile("/proc/sys/net/netfilter/nf_conntrack_count") or "") or 0
|
||||
|
||||
local conn_max = tonumber(luci.sys.exec(
|
||||
"sysctl -n -e net.nf_conntrack_max net.ipv4.netfilter.ip_conntrack_max"
|
||||
):match("%d+")) or 4096
|
||||
|
||||
local cpu_info = luci.sys.exec("cpuinfo")
|
||||
|
||||
local eth_info = luci.sys.exec("ethinfo")
|
||||
|
||||
local user_info = luci.sys.exec("cat /proc/net/arp | grep '0x2' | wc -l") or 0
|
||||
|
||||
local cpu_usage = (luci.sys.exec("expr 100 - $(top -n 1 | grep -E '^CPU:' | awk -F '%' '{print$4}' | awk -F ' ' '{print$2}' | awk '{print int($1 + 0.5)}')") or "6") .. "%"
|
||||
|
||||
local rv = {
|
||||
cpuusage = cpu_usage,
|
||||
cpuinfo = cpu_info,
|
||||
ethinfo = eth_info,
|
||||
userinfo = user_info,
|
||||
uptime = sysinfo.uptime or 0,
|
||||
localtime = os.date(),
|
||||
loadavg = sysinfo.load or { 0, 0, 0 },
|
||||
memory = meminfo,
|
||||
memcached = mem_cached,
|
||||
swap = swapinfo,
|
||||
connmax = conn_max,
|
||||
conncount = conn_count,
|
||||
leases = stat.dhcp_leases(),
|
||||
leases6 = stat.dhcp6_leases(),
|
||||
wifinets = stat.wifi_networks()
|
||||
}
|
||||
|
||||
if wan then
|
||||
rv.wan = {
|
||||
ipaddr = wan:ipaddr(),
|
||||
gwaddr = wan:gwaddr(),
|
||||
netmask = wan:netmask(),
|
||||
dns = wan:dnsaddrs(),
|
||||
expires = wan:expires(),
|
||||
uptime = wan:uptime(),
|
||||
proto = wan:proto(),
|
||||
ifname = wan:ifname(),
|
||||
link = wan:adminlink()
|
||||
}
|
||||
end
|
||||
|
||||
if wan6 then
|
||||
rv.wan6 = {
|
||||
ip6addr = wan6:ip6addr(),
|
||||
gw6addr = wan6:gw6addr(),
|
||||
dns = wan6:dns6addrs(),
|
||||
ip6prefix = wan6:ip6prefix(),
|
||||
uptime = wan6:uptime(),
|
||||
proto = wan6:proto(),
|
||||
ifname = wan6:ifname(),
|
||||
link = wan6:adminlink()
|
||||
}
|
||||
end
|
||||
|
||||
if has_dsl then
|
||||
local dsl_stat = luci.sys.exec("/etc/init.d/dsl_control lucistat")
|
||||
local dsl_func = loadstring(dsl_stat)
|
||||
if dsl_func then
|
||||
rv.dsl = dsl_func()
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
|
||||
return
|
||||
elseif luci.http.formvalue("hosts") == "1" then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(luci.sys.net.host_hints())
|
||||
|
||||
return
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js?v=git-19.167.54478-71e2af4"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function progressbar(v, m)
|
||||
{
|
||||
var vn = parseInt(v) || 0;
|
||||
var mn = parseInt(m) || 100;
|
||||
var pc = Math.floor((100 / mn) * vn);
|
||||
|
||||
return String.format(
|
||||
'<div style="width:200px; position:relative; border:1px solid #999999">' +
|
||||
'<div style="background-color:#CCCCCC; width:%d%%; height:15px">' +
|
||||
'<div style="position:absolute; left:0; top:0; text-align:center; width:100%%; color:#000000">' +
|
||||
'<small>%s / %s (%d%%)</small>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>', pc, v, m, pc
|
||||
);
|
||||
}
|
||||
|
||||
function wifirate(bss, rx) {
|
||||
var p = rx ? 'rx_' : 'tx_',
|
||||
s = '%.1f <%:Mbit/s%>, %d<%:MHz%>'
|
||||
.format(bss[p+'rate'] / 1000, bss[p+'mhz']),
|
||||
ht = bss[p+'ht'], vht = bss[p+'vht'],
|
||||
mhz = bss[p+'mhz'], nss = bss[p+'nss'],
|
||||
mcs = bss[p+'mcs'], sgi = bss[p+'short_gi'],
|
||||
he = bss[p+'he'], he_gi = bss[p+'he_gi'],
|
||||
he_dcm = bss[p+'he_dcm'];
|
||||
|
||||
if (ht || vht) {
|
||||
if (vht) s += ', VHT-MCS %d'.format(mcs);
|
||||
if (nss) s += ', VHT-NSS %d'.format(nss);
|
||||
if (ht) s += ', MCS %s'.format(mcs);
|
||||
if (sgi) s += ', <%:Short GI%>';
|
||||
}
|
||||
|
||||
if (he) {
|
||||
s += ', HE-MCS %d'.format(mcs);
|
||||
if (nss) s += ', HE-NSS %d'.format(nss);
|
||||
if (he_gi) s += ', HE-GI %d'.format(he_gi);
|
||||
if (he_dcm) s += ', HE-DCM %d'.format(he_dcm);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function duid2mac(duid) {
|
||||
// DUID-LLT / Ethernet
|
||||
if (duid.length === 28 && duid.substr(0, 8) === '00010001')
|
||||
return duid.substr(16).replace(/(..)(?=..)/g, '$1:').toUpperCase();
|
||||
|
||||
// DUID-LL / Ethernet
|
||||
if (duid.length === 20 && duid.substr(0, 8) === '00030001')
|
||||
return duid.substr(8).replace(/(..)(?=..)/g, '$1:').toUpperCase();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var npoll = 1;
|
||||
var hosts = <%=luci.http.write_json(luci.sys.net.host_hints())%>;
|
||||
|
||||
function updateHosts() {
|
||||
XHR.get('<%=REQUEST_URI%>', { hosts: 1 }, function(x, data) {
|
||||
hosts = data;
|
||||
});
|
||||
}
|
||||
|
||||
var compare = function (prop) {
|
||||
return function (obj1, obj2) {
|
||||
var val1 = Number(obj1[prop].replaceAll(".",""));
|
||||
var val2 = Number(obj2[prop].replaceAll(".",""));
|
||||
if (val1 < val2) {
|
||||
return -1;
|
||||
} else if (val1 > val2) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
XHR.poll(1, '<%=REQUEST_URI%>', { status: 1 },
|
||||
function(x, info)
|
||||
{
|
||||
if (!(npoll++ % 5))
|
||||
updateHosts();
|
||||
|
||||
var si = document.getElementById('wan4_i');
|
||||
var ss = document.getElementById('wan4_s');
|
||||
var ifc = info.wan;
|
||||
|
||||
if (ifc && ifc.ifname && ifc.proto != 'none')
|
||||
{
|
||||
var s = String.format(
|
||||
'<strong><%:Type%>: </strong>%s<br />' +
|
||||
'<strong><%:Address%>: </strong>%s<br />' +
|
||||
'<strong><%:Netmask%>: </strong>%s<br />' +
|
||||
'<strong><%:Gateway%>: </strong>%s<br />',
|
||||
ifc.proto,
|
||||
(ifc.ipaddr) ? ifc.ipaddr : '0.0.0.0',
|
||||
(ifc.netmask && ifc.netmask != ifc.ipaddr) ? ifc.netmask : '255.255.255.255',
|
||||
(ifc.gwaddr) ? ifc.gwaddr : '0.0.0.0'
|
||||
);
|
||||
|
||||
for (var i = 0; i < ifc.dns.length; i++)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:DNS%> %d: </strong>%s<br />',
|
||||
i + 1, ifc.dns[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.expires > -1)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Expires%>: </strong>%t<br />',
|
||||
ifc.expires
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.uptime > 0)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Connected%>: </strong>%t<br />',
|
||||
ifc.uptime
|
||||
);
|
||||
}
|
||||
|
||||
ss.innerHTML = String.format('<small>%s</small>', s);
|
||||
si.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/ethernet.png" />' +
|
||||
'<br /><small><a href="%s">%s</a></small>',
|
||||
ifc.link, ifc.ifname
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
si.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
|
||||
ss.innerHTML = '<em><%:Not connected%></em>';
|
||||
}
|
||||
|
||||
<% if has_ipv6 then %>
|
||||
var si6 = document.getElementById('wan6_i');
|
||||
var ss6 = document.getElementById('wan6_s');
|
||||
var ifc6 = info.wan6;
|
||||
|
||||
if (ifc6 && ifc6.ifname && ifc6.proto != 'none')
|
||||
{
|
||||
var s = String.format(
|
||||
'<strong><%:Type%>: </strong>%s%s<br />',
|
||||
ifc6.proto, (ifc6.ip6prefix) ? '-pd' : ''
|
||||
);
|
||||
|
||||
if (!ifc6.ip6prefix)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Address%>: </strong>%s<br />',
|
||||
(ifc6.ip6addr) ? ifc6.ip6addr : '::'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Prefix Delegated%>: </strong>%s<br />',
|
||||
ifc6.ip6prefix
|
||||
);
|
||||
if (ifc6.ip6addr)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Address%>: </strong>%s<br />',
|
||||
ifc6.ip6addr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
s += String.format(
|
||||
'<strong><%:Gateway%>: </strong>%s<br />',
|
||||
(ifc6.gw6addr) ? ifc6.gw6addr : '::'
|
||||
);
|
||||
|
||||
for (var i = 0; i < ifc6.dns.length; i++)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:DNS%> %d: </strong>%s<br />',
|
||||
i + 1, ifc6.dns[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc6.uptime > 0)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Connected%>: </strong>%t<br />',
|
||||
ifc6.uptime
|
||||
);
|
||||
}
|
||||
|
||||
ss6.innerHTML = String.format('<small>%s</small>', s);
|
||||
si6.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/ethernet.png" />' +
|
||||
'<br /><small><a href="%s">%s</a></small>',
|
||||
ifc6.link, ifc6.ifname
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
si6.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
|
||||
ss6.innerHTML = '<em><%:Not connected%></em>';
|
||||
}
|
||||
<% end %>
|
||||
|
||||
<% if has_dsl then %>
|
||||
var dsl_i = document.getElementById('dsl_i');
|
||||
var dsl_s = document.getElementById('dsl_s');
|
||||
|
||||
var s = String.format(
|
||||
'<strong><%:Status%>: </strong>%s<br />' +
|
||||
'<strong><%:Line State%>: </strong>%s [0x%x]<br />' +
|
||||
'<strong><%:Line Mode%>: </strong>%s<br />' +
|
||||
'<strong><%:Annex%>: </strong>%s<br />' +
|
||||
'<strong><%:Profile%>: </strong>%s<br />' +
|
||||
'<strong><%:Data Rate%>: </strong>%s/s / %s/s<br />' +
|
||||
'<strong><%:Max. Attainable Data Rate (ATTNDR)%>: </strong>%s/s / %s/s<br />' +
|
||||
'<strong><%:Latency%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Line Attenuation (LATN)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Signal Attenuation (SATN)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Noise Margin (SNR)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Aggregate Transmit Power(ACTATP)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Forward Error Correction Seconds (FECS)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Errored seconds (ES)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Severely Errored Seconds (SES)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Loss of Signal Seconds (LOSS)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Unavailable Seconds (UAS)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Header Error Code Errors (HEC)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Non Pre-emtive CRC errors (CRC_P)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Pre-emtive CRC errors (CRCP_P)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Line Uptime%>: </strong>%s<br />' +
|
||||
'<strong><%:ATU-C System Vendor ID%>: </strong>%s<br />' +
|
||||
'<strong><%:Power Management Mode%>: </strong>%s<br />',
|
||||
info.dsl.line_state, info.dsl.line_state_detail,
|
||||
info.dsl.line_state_num,
|
||||
info.dsl.line_mode_s,
|
||||
info.dsl.annex_s,
|
||||
info.dsl.profile_s,
|
||||
info.dsl.data_rate_down_s, info.dsl.data_rate_up_s,
|
||||
info.dsl.max_data_rate_down_s, info.dsl.max_data_rate_up_s,
|
||||
info.dsl.latency_num_down, info.dsl.latency_num_up,
|
||||
info.dsl.line_attenuation_down, info.dsl.line_attenuation_up,
|
||||
info.dsl.signal_attenuation_down, info.dsl.signal_attenuation_up,
|
||||
info.dsl.noise_margin_down, info.dsl.noise_margin_up,
|
||||
info.dsl.actatp_down, info.dsl.actatp_up,
|
||||
info.dsl.errors_fec_near, info.dsl.errors_fec_far,
|
||||
info.dsl.errors_es_near, info.dsl.errors_es_far,
|
||||
info.dsl.errors_ses_near, info.dsl.errors_ses_far,
|
||||
info.dsl.errors_loss_near, info.dsl.errors_loss_far,
|
||||
info.dsl.errors_uas_near, info.dsl.errors_uas_far,
|
||||
info.dsl.errors_hec_near, info.dsl.errors_hec_far,
|
||||
info.dsl.errors_crc_p_near, info.dsl.errors_crc_p_far,
|
||||
info.dsl.errors_crcp_p_near, info.dsl.errors_crcp_p_far,
|
||||
info.dsl.line_uptime_s,
|
||||
info.dsl.atuc_vendor_id,
|
||||
info.dsl.power_mode_s
|
||||
);
|
||||
|
||||
dsl_s.innerHTML = String.format('<small>%s</small>', s);
|
||||
dsl_i.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/ethernet.png" />' +
|
||||
'<br /><small>DSL</small>'
|
||||
);
|
||||
<% end %>
|
||||
|
||||
<% if has_dhcp then %>
|
||||
var ls = document.getElementById('lease_status_table');
|
||||
if (ls)
|
||||
{
|
||||
info.leases = info.leases.sort(compare("ipaddr"));
|
||||
/* clear all rows */
|
||||
while( ls.rows.length > 1 )
|
||||
ls.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
for( var i = 0; i < info.leases.length; i++ )
|
||||
{
|
||||
var timestr;
|
||||
|
||||
if (info.leases[i].expires === false)
|
||||
timestr = '<em><%:unlimited%></em>';
|
||||
else if (info.leases[i].expires <= 0)
|
||||
timestr = '<em><%:expired%></em>';
|
||||
else
|
||||
timestr = String.format('%t', info.leases[i].expires);
|
||||
|
||||
var tr = ls.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
|
||||
|
||||
tr.insertCell(-1).innerHTML = info.leases[i].hostname ? info.leases[i].hostname : '?';
|
||||
tr.insertCell(-1).innerHTML = info.leases[i].ipaddr;
|
||||
tr.insertCell(-1).innerHTML = info.leases[i].macaddr;
|
||||
tr.insertCell(-1).innerHTML = timestr;
|
||||
}
|
||||
|
||||
if( ls.rows.length == 1 )
|
||||
{
|
||||
var tr = ls.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 4;
|
||||
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
|
||||
}
|
||||
}
|
||||
|
||||
var ls6 = document.getElementById('lease6_status_table');
|
||||
if (ls6 && info.leases6)
|
||||
{
|
||||
ls6.parentNode.style.display = 'block';
|
||||
|
||||
/* clear all rows */
|
||||
while( ls6.rows.length > 1 )
|
||||
ls6.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
for( var i = 0; i < info.leases6.length; i++ )
|
||||
{
|
||||
var timestr;
|
||||
|
||||
if (info.leases6[i].expires === false)
|
||||
timestr = '<em><%:unlimited%></em>';
|
||||
else if (info.leases6[i].expires <= 0)
|
||||
timestr = '<em><%:expired%></em>';
|
||||
else
|
||||
timestr = String.format('%t', info.leases6[i].expires);
|
||||
|
||||
var tr = ls6.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
|
||||
|
||||
var host = hosts[duid2mac(info.leases6[i].duid)];
|
||||
if (!info.leases6[i].hostname)
|
||||
tr.insertCell(-1).innerHTML =
|
||||
(host && (host.name || host.ipv4 || host.ipv6))
|
||||
? '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space: nowrap">? (%h)</div>'.format(host.name || host.ipv4 || host.ipv6)
|
||||
: '?';
|
||||
else
|
||||
tr.insertCell(-1).innerHTML =
|
||||
(host && host.name && info.leases6[i].hostname != host.name)
|
||||
? '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space: nowrap">%h (%h)</div>'.format(info.leases6[i].hostname, host.name)
|
||||
: info.leases6[i].hostname;
|
||||
|
||||
tr.insertCell(-1).innerHTML = info.leases6[i].ip6addr;
|
||||
tr.insertCell(-1).innerHTML = info.leases6[i].duid;
|
||||
tr.insertCell(-1).innerHTML = timestr;
|
||||
}
|
||||
|
||||
if( ls6.rows.length == 1 )
|
||||
{
|
||||
var tr = ls6.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 4;
|
||||
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
|
||||
}
|
||||
}
|
||||
<% end %>
|
||||
|
||||
<% if has_wifi then %>
|
||||
var assoclist = [ ];
|
||||
|
||||
var ws = document.getElementById('wifi_status_table');
|
||||
if (ws)
|
||||
{
|
||||
var wsbody = ws.rows[0].parentNode;
|
||||
while (ws.rows.length > 0)
|
||||
wsbody.deleteRow(0);
|
||||
|
||||
for (var didx = 0; didx < info.wifinets.length; didx++)
|
||||
{
|
||||
var dev = info.wifinets[didx];
|
||||
|
||||
var tr = wsbody.insertRow(-1);
|
||||
var td;
|
||||
|
||||
td = tr.insertCell(-1);
|
||||
td.width = "33%";
|
||||
td.innerHTML = dev.name;
|
||||
td.style.verticalAlign = "top";
|
||||
|
||||
td = tr.insertCell(-1);
|
||||
|
||||
var s = '';
|
||||
|
||||
for (var nidx = 0; nidx < dev.networks.length; nidx++)
|
||||
{
|
||||
var net = dev.networks[nidx];
|
||||
var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel && !net.disabled);
|
||||
|
||||
var icon;
|
||||
if (!is_assoc)
|
||||
icon = "<%=resource%>/icons/signal-none.png";
|
||||
else if (net.quality == 0)
|
||||
icon = "<%=resource%>/icons/signal-0.png";
|
||||
else if (net.quality < 25)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (net.quality < 50)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (net.quality < 75)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
s += String.format(
|
||||
'<table><tr><td style="text-align:center; width:32px; padding:3px">' +
|
||||
'<img src="%s" title="<%:Signal%>: %d dBm / <%:Noise%>: %d dBm" />' +
|
||||
'<br /><small>%d%%</small>' +
|
||||
'</td><td style="text-align:left; padding:3px"><small>' +
|
||||
'<strong><%:SSID%>:</strong> <a href="%s">%h</a><br />' +
|
||||
'<strong><%:Mode%>:</strong> %s<br />' +
|
||||
'<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>)<br />' +
|
||||
'<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%><br />',
|
||||
icon, net.signal, net.noise,
|
||||
net.quality,
|
||||
net.link, net.ssid || '?',
|
||||
net.mode,
|
||||
net.channel, net.frequency,
|
||||
net.bitrate || '?'
|
||||
);
|
||||
|
||||
if (is_assoc)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:BSSID%>:</strong> %s<br />' +
|
||||
'<strong><%:Encryption%>:</strong> %s',
|
||||
net.bssid || '?',
|
||||
net.encryption
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
s += '<em><%:Wireless is disabled or not associated%></em>';
|
||||
}
|
||||
|
||||
s += '</small></td></tr></table>';
|
||||
|
||||
for (var bssid in net.assoclist)
|
||||
{
|
||||
var bss = net.assoclist[bssid];
|
||||
|
||||
bss.bssid = bssid;
|
||||
bss.link = net.link;
|
||||
bss.name = net.name;
|
||||
bss.ifname = net.ifname;
|
||||
bss.radio = dev.name;
|
||||
|
||||
assoclist.push(bss);
|
||||
}
|
||||
}
|
||||
|
||||
if (!s)
|
||||
s = '<em><%:No information available%></em>';
|
||||
|
||||
td.innerHTML = s;
|
||||
}
|
||||
}
|
||||
|
||||
var ac = document.getElementById('wifi_assoc_table');
|
||||
if (ac)
|
||||
{
|
||||
/* clear all rows */
|
||||
while( ac.rows.length > 1 )
|
||||
ac.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
assoclist.sort(function(a, b) {
|
||||
return (a.name == b.name)
|
||||
? (a.bssid < b.bssid)
|
||||
: (a.name > b.name )
|
||||
;
|
||||
});
|
||||
|
||||
for( var i = 0; i < assoclist.length; i++ )
|
||||
{
|
||||
var tr = ac.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
|
||||
|
||||
var icon;
|
||||
var q = (-1 * (assoclist[i].noise - assoclist[i].signal)) / 5;
|
||||
if (q < 1)
|
||||
icon = "<%=resource%>/icons/signal-0.png";
|
||||
else if (q < 2)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (q < 3)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (q < 4)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> %h</span>',
|
||||
assoclist[i].radio, assoclist[i].ifname
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<a href="%s">%s</a>',
|
||||
assoclist[i].link,
|
||||
'%h'.format(assoclist[i].name).nobr()
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = assoclist[i].bssid;
|
||||
|
||||
var host = hosts[assoclist[i].bssid];
|
||||
if (host)
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
|
||||
((host.name && (host.ipv4 || host.ipv6))
|
||||
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
|
||||
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
|
||||
);
|
||||
else
|
||||
tr.insertCell(-1).innerHTML = '?';
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>',
|
||||
assoclist[i].signal, assoclist[i].noise, assoclist[i].signal - assoclist[i].noise,
|
||||
icon,
|
||||
assoclist[i].signal, assoclist[i].noise
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = wifirate(assoclist[i], true).nobr() + '<br />' + wifirate(assoclist[i], false).nobr();
|
||||
}
|
||||
|
||||
if (ac.rows.length == 1)
|
||||
{
|
||||
var tr = ac.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 7;
|
||||
td.innerHTML = '<br /><em><%:No information available%></em>';
|
||||
}
|
||||
}
|
||||
<% end %>
|
||||
|
||||
var e;
|
||||
|
||||
if (e = document.getElementById('ethinfo')) {
|
||||
var ports = eval('(' + info.ethinfo + ')');
|
||||
var tmp = "";
|
||||
for (var i in ports)
|
||||
{
|
||||
tmp = tmp + String.format(
|
||||
'<td style="text-align:center"><span style="line-height:25px">%s</span><br /><small><img src="<%=resource%>/icons/%s" /><br />%s<br />%s</small></td>', ports[i].name,
|
||||
ports[i].status ? 'port_up.png' : 'port_down.png',
|
||||
ports[i].speed,
|
||||
ports[i].duplex ? '<%:full-duplex%>' : '<%:half-duplex%>');
|
||||
};
|
||||
e.innerHTML = "<tr>" + tmp + "</tr>";
|
||||
}
|
||||
|
||||
if (e = document.getElementById('localtime'))
|
||||
e.innerHTML = info.localtime;
|
||||
|
||||
if (e = document.getElementById('uptime'))
|
||||
e.innerHTML = String.format('%t', info.uptime);
|
||||
|
||||
if (e = document.getElementById('userinfo'))
|
||||
e.innerHTML = info.userinfo;
|
||||
|
||||
if (e = document.getElementById('cpuinfo'))
|
||||
e.innerHTML = info.cpuinfo;
|
||||
|
||||
if (e = document.getElementById('cpuusage'))
|
||||
e.innerHTML = info.cpuusage;
|
||||
|
||||
if (e = document.getElementById('loadavg'))
|
||||
e.innerHTML = String.format(
|
||||
'%.02f, %.02f, %.02f',
|
||||
info.loadavg[0] / 65535.0,
|
||||
info.loadavg[1] / 65535.0,
|
||||
info.loadavg[2] / 65535.0
|
||||
);
|
||||
|
||||
if (e = document.getElementById('memtotal'))
|
||||
e.innerHTML = progressbar(
|
||||
Math.floor(((info.memory.free + info.memory.buffered) / 1048576) + (info.memcached / 1024)) + " <%:MB%>",
|
||||
Math.floor(info.memory.total / 1048576) + " <%:MB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('membuff'))
|
||||
e.innerHTML = progressbar(
|
||||
Math.floor(info.memory.buffered / 1048576) + " <%:MB%>",
|
||||
Math.floor(info.memory.total / 1048576) + " <%:MB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('swaptotal'))
|
||||
e.innerHTML = progressbar(
|
||||
Math.floor(info.swap.free / 1048576) + " <%:MB%>",
|
||||
Math.floor(info.swap.total / 1048576) + " <%:MB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('swapfree'))
|
||||
e.innerHTML = progressbar(
|
||||
Math.floor(info.swap.free / 1048576) + " <%:MB%>",
|
||||
Math.floor(info.swap.total / 1048576) + " <%:MB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('conns'))
|
||||
e.innerHTML = progressbar(info.conncount, info.connmax);
|
||||
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Status%></h2>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:System%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%"><%:Hostname%></td><td><%=luci.sys.hostname() or "?"%></td></tr>
|
||||
<tr><td width="33%"><%:Model%></td><td><%=pcdata(boardinfo.model or "?")%> <%=luci.sys.exec("cat /etc/bench.log") or " "%></td></tr>
|
||||
<tr><td width="33%"><%:CPU Info%></td><td id="cpuinfo">-</td></tr>
|
||||
<tr><td width="33%"><%:Firmware Version%></td><td>
|
||||
<%=pcdata(ver.distname)%> <%=pcdata(ver.distversion)%> /
|
||||
<%=pcdata(ver.luciname)%> (<%=pcdata(ver.luciversion)%>)
|
||||
</td></tr>
|
||||
<tr><td width="33%"><%:Kernel Version%></td><td><%=unameinfo.release or "?"%></td></tr>
|
||||
<tr><td width="33%"><%:Local Time%></td><td id="localtime">-</td></tr>
|
||||
<tr><td width="33%"><%:Uptime%></td><td id="uptime">-</td></tr>
|
||||
<tr><td width="33%"><%:Load Average%></td><td id="loadavg">-</td></tr>
|
||||
<tr><td width="33%"><%:CPU usage (%)%></td><td id="cpuusage">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Memory%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%"><%:Total Available%></td><td id="memtotal">-</td></tr>
|
||||
<tr><td width="33%"><%:Buffered%></td><td id="membuff">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<% if swapinfo.total > 0 then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Swap%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%"><%:Total Available%></td><td id="swaptotal">-</td></tr>
|
||||
<tr><td width="33%"><%:Free%></td><td id="swapfree">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Interfaces%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10" id="ethinfo">
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Network%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%" style="vertical-align:top"><%:IPv4 WAN Status%></td><td>
|
||||
<table><tr>
|
||||
<td id="wan4_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
|
||||
<td id="wan4_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
<% if has_ipv6 then %>
|
||||
<tr><td width="33%" style="vertical-align:top"><%:IPv6 WAN Status%></td><td>
|
||||
<table><tr>
|
||||
<td id="wan6_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
|
||||
<td id="wan6_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
<% end %>
|
||||
<tr><td width="33%"><%:Online Users%></td><td id="userinfo">0</td></tr>
|
||||
<tr><td width="33%"><%:Active Connections%></td><td id="conns">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<% if has_dhcp then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:DHCP Leases%></legend>
|
||||
|
||||
<table class="cbi-section-table" id="lease_status_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Hostname%></th>
|
||||
<th class="cbi-section-table-cell"><%:IPv4-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<% if has_ipv6 then %>
|
||||
<fieldset class="cbi-section" style="display:none">
|
||||
<legend><%:DHCPv6 Leases%></legend>
|
||||
|
||||
<table class="cbi-section-table" id="lease6_status_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Host%></th>
|
||||
<th class="cbi-section-table-cell"><%:IPv6-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:DUID%></th>
|
||||
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if has_dsl then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:DSL%></legend>
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%" style="vertical-align:top"><%:DSL Status%></td><td>
|
||||
<table><tr>
|
||||
<td id="dsl_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
|
||||
<td id="dsl_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<% if has_wifi then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Wireless%></legend>
|
||||
|
||||
<table id="wifi_status_table" width="100%" cellspacing="10">
|
||||
<tr><td><em><%:Collecting data...%></em></td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<%+footer%>
|
||||
@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
arch="$(awk -F ': ' '/model name/ {print $2}' "/proc/cpuinfo" | head -n1)"
|
||||
|
||||
core="$(grep "core id" "/proc/cpuinfo" | sort -u | wc -l)C $(grep -c "processor" "/proc/cpuinfo")T"
|
||||
|
||||
freq="$(awk -F ': ' '/MHz/ {print $2}' "/proc/cpuinfo" | head -n1)MHz"
|
||||
|
||||
# Intel
|
||||
temp="$(sensors "coretemp-*" 2>"/dev/null" | grep -E "(Package id |Core )" | grep -Eo "\+[0-9.]*°C" | head -n1 | tr -d "+")"
|
||||
# AMD
|
||||
[ -n "${temp}" ] || temp="$(sensors "k*temp-*" 2>"/dev/null" | awk '/Tdie/ {print $2}' | head -n1 | tr -d "+")"
|
||||
|
||||
echo -n "$arch x $core ($freq, ${temp})"
|
||||
@ -1,39 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
a=$(ip address | grep ^[0-9] | awk -F: '{print $2}' | sed "s/ //g" | grep '^[e]' | grep -v "@" | grep -v "\.")
|
||||
b=$(echo "$a" | wc -l)
|
||||
rm -f /tmp/state/ethinfo
|
||||
|
||||
echo -n "[" > /tmp/state/ethinfo
|
||||
|
||||
for i in $(seq 1 $b)
|
||||
do
|
||||
h=$(echo '{"name":' )
|
||||
c=$(echo "$a" | sed -n ${i}p)
|
||||
d=$(ethtool $c)
|
||||
|
||||
e=$(echo "$d" | grep "Link detected" | awk -F: '{printf $2}' | sed 's/^[ \t]*//g')
|
||||
if [ $e = yes ]; then
|
||||
l=1
|
||||
else
|
||||
l=0
|
||||
fi
|
||||
|
||||
f=$(echo "$d" | grep "Speed" | awk -F: '{printf $2}' | sed 's/^[ \t]*//g' | tr -d "Unknown!")
|
||||
[ -z "$f" ] && f=" - "
|
||||
|
||||
g=$(echo "$d" | grep "Duplex" | awk -F: '{printf $2}' | sed 's/^[ \t]*//g')
|
||||
if [ "$g" == "Full" ]; then
|
||||
x=1
|
||||
else
|
||||
x=0
|
||||
fi
|
||||
|
||||
echo -n "$h \"$c\", \"status\": $l, \"speed\": \"$f\", \"duplex\": $x}," >> /tmp/state/ethinfo
|
||||
done
|
||||
|
||||
sed -i 's/.$//' /tmp/state/ethinfo
|
||||
|
||||
echo -n "]" >> /tmp/state/ethinfo
|
||||
|
||||
cat /tmp/state/ethinfo
|
||||
@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $(busybox ps -w | grep getcpu | grep -v grep | wc -l) -le 2 ]; then
|
||||
AT=$(cat /proc/stat | grep "^cpu " | awk '{print $2+$3+$4+$5+$6+$7+$8 " " $2+$3+$4+$7+$8}')
|
||||
sleep 1
|
||||
BT=$(cat /proc/stat | grep "^cpu " | awk '{print $2+$3+$4+$5+$6+$7+$8 " " $2+$3+$4+$7+$8}')
|
||||
printf "%.01f%%" $(echo $AT $BT | awk '{print (($4-$2)/($3-$1))*100}') >/tmp/cpuusage
|
||||
fi
|
||||
@ -1,37 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2010-2011 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=automount
|
||||
PKG_VERSION:=1
|
||||
PKG_RELEASE:=40
|
||||
PKG_ARCH:=all
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/automount
|
||||
TITLE:=Mount autoconfig hotplug script.
|
||||
MAINTAINER:=Lean
|
||||
DEPENDS:=+block-mount +kmod-fs-exfat +kmod-fs-ext4 +kmod-fs-vfat +libblkid \
|
||||
+kmod-usb-storage +kmod-usb-storage-extras +!TARGET_ramips:kmod-usb-storage-uas +kmod-fs-ntfs3
|
||||
endef
|
||||
|
||||
define Package/automount/description
|
||||
A usb autoconfig hotplug script.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/automount/install
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/15-automount $(1)/etc/15-automount
|
||||
$(INSTALL_BIN) ./files/zzz-move-automount $(1)/etc/uci-defaults/zzz-move-automount
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,automount))
|
||||
@ -1,27 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2015 OpenWrt.org
|
||||
|
||||
# 0 yes blockdevice handles this - 1 no it is not there
|
||||
blkdev=`dirname $DEVPATH`
|
||||
basename=`basename $blkdev`
|
||||
device=`basename $DEVPATH`
|
||||
skip=`block info | grep -vE '(f2fs|kernel|squashfs)' | sed 's/\(.*\): .*/\1/' | grep -q $device ; echo $?`
|
||||
path=$DEVPATH
|
||||
|
||||
if [ $basename != "block" ] && [ -z "${device##sd*}" ] && [ $skip -eq 1 ]; then
|
||||
mntpnt=$device
|
||||
case "$ACTION" in
|
||||
add)
|
||||
mkdir -p /mnt/$mntpnt
|
||||
chmod 777 /mnt/$mntpnt
|
||||
# Try to be gentle on solid state devices
|
||||
mount -o rw,noatime,discard /dev/$device /mnt/$mntpnt
|
||||
;;
|
||||
remove)
|
||||
# Once the device is removed, the /dev entry disappear. We need mountpoint
|
||||
mountpoint=`mount |grep /dev/$device | sed 's/.* on \(.*\) type.*/\1/'`
|
||||
umount -l $mountpoint
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
sleep 15
|
||||
mv /etc/15-automount /etc/hotplug.d/block/
|
||||
@ -1,57 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2010-2011 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=autosamba
|
||||
PKG_VERSION:=1
|
||||
PKG_RELEASE:=15
|
||||
PKG_ARCH:=all
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_KSMBD \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA3 \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA4 \
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/autosamba
|
||||
TITLE:=Samba autoconfig hotplug script.
|
||||
MAINTAINER:=Lean
|
||||
DEPENDS:=+wsdd2 +PACKAGE_$(PKG_NAME)_INCLUDE_KSMBD:luci-app-ksmbd +PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA3:luci-app-samba +PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA4:luci-app-samba4
|
||||
endef
|
||||
|
||||
define Package/autosamba/description
|
||||
A hotplug script to config Samba share automatically.
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/config
|
||||
choice
|
||||
prompt "Samba Server Selection"
|
||||
default PACKAGE_$(PKG_NAME)_INCLUDE_KSMBD
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_KSMBD
|
||||
bool "KSMBD"
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA3
|
||||
bool "SAMBA 3"
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA4
|
||||
bool "SAMBA 4"
|
||||
endchoice
|
||||
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/autosamba/install
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/block
|
||||
$(INSTALL_BIN) ./files/20-smb $(1)/etc/hotplug.d/block/20-smb
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,autosamba))
|
||||
@ -1,106 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# D-Team Technology Co.,Ltd. ShenZhen
|
||||
# 作者:Vic
|
||||
#
|
||||
# 警告:对着屏幕的哥们,我们允许你使用此脚本,但不允许你抹去作者的信息,请保留这段话。
|
||||
#
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/service.sh
|
||||
|
||||
global=0
|
||||
config_file="/etc/config/samba4"
|
||||
|
||||
wait_for_init() {
|
||||
for i in `seq 30`
|
||||
do
|
||||
[ -e /tmp/procd.done ] || {
|
||||
sleep 1; continue;
|
||||
}
|
||||
return
|
||||
done
|
||||
}
|
||||
|
||||
smb_handle() {
|
||||
config_get path $1 path
|
||||
if [ "$path" = "$2" ] ;then
|
||||
global=1
|
||||
fi
|
||||
}
|
||||
|
||||
chk_en() {
|
||||
config_get_bool autoshare $1 autoshare 1
|
||||
[ $autoshare -eq 0 ] && exit
|
||||
}
|
||||
|
||||
config_load samba4
|
||||
config_foreach chk_en samba4
|
||||
|
||||
device=`basename $DEVPATH`
|
||||
|
||||
case "$ACTION" in
|
||||
add)
|
||||
|
||||
case "$device" in
|
||||
sd*);;
|
||||
md*);;
|
||||
hd*);;
|
||||
mmcblk*);;
|
||||
*) return;;
|
||||
esac
|
||||
|
||||
path="/dev/$device"
|
||||
|
||||
wait_for_init
|
||||
|
||||
cat /proc/mounts | grep -v '/boot\|/opt' | while read j
|
||||
do
|
||||
str=${j%% *}
|
||||
if [ "$str" == $path ];then
|
||||
strr=${j#* }
|
||||
target=${strr%% *}
|
||||
global=0
|
||||
config_foreach smb_handle sambashare $target
|
||||
name=${target#*/mnt/}
|
||||
|
||||
if [ $global -eq 0 ] ;then
|
||||
echo -e "\n\nconfig sambashare" >> $config_file
|
||||
echo -e "\toption auto '1'" >> $config_file
|
||||
echo -e "\toption name '$name'" >> $config_file
|
||||
echo -e "\toption path '$target'" >> $config_file
|
||||
echo -e "\toption read_only 'no'" >> $config_file
|
||||
echo -e "\toption guest_ok 'yes'" >> $config_file
|
||||
echo -e "\toption create_mask '0666'" >> $config_file
|
||||
echo -e "\toption dir_mask '0777'" >> $config_file
|
||||
echo -e "\toption device '$device'" >> $config_file
|
||||
echo -e "\toption inherit_owner 'yes'" >> $config_file
|
||||
/etc/init.d/samba4 reload
|
||||
return
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
|
||||
remove)
|
||||
i=0
|
||||
while true
|
||||
do
|
||||
dev=`uci get samba4.@sambashare[$i].device`
|
||||
[ $? -ne 0 ] && break
|
||||
|
||||
[ "$dev" = "$device" ] && {
|
||||
auto=`uci get samba4.@sambashare[$i].auto`
|
||||
[ $auto = "1" ] && {
|
||||
mount_dir=`uci get samba4.@sambashare[$i].name`
|
||||
uci delete samba4.@sambashare[$i]
|
||||
uci commit
|
||||
/etc/init.d/samba4 reload
|
||||
return
|
||||
}
|
||||
}
|
||||
let i+=1
|
||||
done
|
||||
;;
|
||||
esac
|
||||
@ -1,30 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Copyright (C) 2024 ImmortalWrt.org
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=cpufreq
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/cpufreq
|
||||
TITLE:=CPU Frequency Scaling adjustment tool
|
||||
DEPENDS:=@(arm||aarch64)
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/cpufreq/install
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) $(CURDIR)/files/cpufreq.config $(1)/etc/config/cpufreq
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) $(CURDIR)/files/cpufreq.init $(1)/etc/init.d/cpufreq
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) $(CURDIR)/files/cpufreq.uci $(1)/etc/uci-defaults/10-cpufreq
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,cpufreq))
|
||||
@ -1,5 +0,0 @@
|
||||
|
||||
config settings 'cpufreq'
|
||||
|
||||
config settings 'global'
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=15
|
||||
USE_PROCD=1
|
||||
|
||||
NAME="cpufreq"
|
||||
CPUFREQ_PATH="/sys/devices/system/cpu/cpufreq"
|
||||
|
||||
extra_command "get_policies" "Get CPU scaling governors and frequencies"
|
||||
|
||||
get_policies() {
|
||||
json_init
|
||||
for policy in $(ls -d "$CPUFREQ_PATH"/policy[0-9]* 2>"/dev/null"); do
|
||||
[ -s "$policy/scaling_available_frequencies" ] || continue
|
||||
json_add_object "$(basename "$policy")"
|
||||
json_add_string "index" "$(basename "$policy" | grep -Eo "[0-9]*$")"
|
||||
json_add_string "cpus" "$(cat "$policy/affected_cpus")"
|
||||
json_add_array "freqs"
|
||||
for freq in $(cat "$policy/scaling_available_frequencies"); do
|
||||
json_add_string "" "$freq"
|
||||
done
|
||||
json_close_array
|
||||
json_add_array "governors"
|
||||
for governor in $(cat "$policy/scaling_available_governors"); do
|
||||
json_add_string "" "$governor"
|
||||
done
|
||||
json_close_array
|
||||
json_close_object
|
||||
done
|
||||
json_dump
|
||||
}
|
||||
|
||||
write_cpufreq_config() {
|
||||
local value
|
||||
config_get value "$NAME" "$1"
|
||||
[ -z "$value" ] || echo -n "$value" > "$2"
|
||||
}
|
||||
|
||||
start_service() {
|
||||
config_load "$NAME"
|
||||
|
||||
for i in $(ls -d "$CPUFREQ_PATH"/policy[0-9]* 2>"/dev/null" | grep -Eo "[0-9]*$")
|
||||
do
|
||||
[ -z "$(config_get "$NAME" "governor$i")" ] && return
|
||||
|
||||
write_cpufreq_config "governor$i" "$CPUFREQ_PATH/policy$i/scaling_governor"
|
||||
write_cpufreq_config "minfreq$i" "$CPUFREQ_PATH/policy$i/scaling_min_freq"
|
||||
write_cpufreq_config "maxfreq$i" "$CPUFREQ_PATH/policy$i/scaling_max_freq"
|
||||
if [ "$(config_get "$NAME" "governor$i")" = "ondemand" ]; then
|
||||
write_cpufreq_config "sdfactor$i" "$CPUFREQ_PATH/ondemand/sampling_down_factor"
|
||||
write_cpufreq_config "upthreshold$i" "$CPUFREQ_PATH/ondemand/up_threshold"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "$NAME"
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci_write_config() {
|
||||
uci -q set "cpufreq.cpufreq.governor$1"="$2"
|
||||
uci -q set "cpufreq.cpufreq.minfreq$1"="$3"
|
||||
uci -q set "cpufreq.cpufreq.maxfreq$1"="$4"
|
||||
[ -n "$5" ] && uci -q set "cpufreq.cpufreq.sdfactor$1"="$5"
|
||||
[ -n "$6" ] && uci -q set "cpufreq.cpufreq.upthreshold$1"="$6"
|
||||
uci -q commit cpufreq
|
||||
}
|
||||
|
||||
[ "$(uci -q get cpufreq.global.set)" -eq "1" ] && exit 0
|
||||
|
||||
CPU_FREQS="$(cat '/sys/devices/system/cpu/cpufreq/policy0/scaling_available_frequencies')"
|
||||
CPU_MIN_FREQ="$(cat '/sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq')"
|
||||
CPU_MAX_FREQ="$(cat '/sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq')"
|
||||
CPU_POLICYS="$(find '/sys/devices/system/cpu/cpufreq/policy'* -maxdepth 0 | grep -Eo '[0-9]+')"
|
||||
|
||||
source "/etc/openwrt_release"
|
||||
case "$DISTRIB_TARGET" in
|
||||
"bcm27xx/bcm2710"|\
|
||||
"bcm27xx/bcm2711")
|
||||
uci_write_config 0 ondemand 600000 "$CPU_MAX_FREQ" 10 50
|
||||
;;
|
||||
"ipq40xx/generic")
|
||||
uci_write_config 0 performance 200000 "$CPU_MAX_FREQ"
|
||||
;;
|
||||
"ipq806x/generic")
|
||||
uci_write_config 0 performance 600000 "$CPU_MAX_FREQ"
|
||||
# IPQ8064/5
|
||||
echo "$CPU_POLICYS" | grep -q "1" && uci_write_config 1 performance 600000 1200000
|
||||
;;
|
||||
"mediatek/mt7622")
|
||||
uci_write_config 0 ondemand 600000 1350000 10 50
|
||||
;;
|
||||
"qualcommax/ipq60xx"|\
|
||||
"qualcommax/ipq807x")
|
||||
uci_write_config 0 schedutil "$CPU_MIN_FREQ" "$CPU_MAX_FREQ"
|
||||
;;
|
||||
"rockchip/armv8")
|
||||
if echo "$CPU_POLICYS" | grep -q "6"; then
|
||||
# RK3588/S
|
||||
uci_write_config 0 schedutil 1008000 1800000
|
||||
uci_write_config 4 schedutil 816000 2208000
|
||||
uci_write_config 6 schedutil 816000 2208000
|
||||
elif echo "$CPU_POLICYS" | grep -q "4"; then
|
||||
# RK3399
|
||||
uci_write_config 0 schedutil 600000 1608000
|
||||
uci_write_config 4 schedutil 600000 2016000
|
||||
else
|
||||
if ! echo "$CPU_FREQS" | grep -q "1992000"; then
|
||||
# RK3328
|
||||
CPU_MAX_FREQ="1512000"
|
||||
fi
|
||||
uci_write_config 0 schedutil 816000 "$CPU_MAX_FREQ"
|
||||
fi
|
||||
;;
|
||||
"sunxi/cortexa53")
|
||||
if echo "$CPU_FREQS" | grep -q "1800000"; then
|
||||
# H6
|
||||
uci_write_config 0 schedutil "888000" "$CPU_MAX_FREQ"
|
||||
elif echo "$CPU_FREQS" | grep -q "1512000"; then
|
||||
# H616/8
|
||||
uci_write_config 0 schedutil "936000" "1512000"
|
||||
elif echo "$CPU_FREQS" | grep -q "1296000"; then
|
||||
# H5
|
||||
uci_write_config 0 ondemand "$CPU_MIN_FREQ" "1296000" 10 50
|
||||
else
|
||||
# A64
|
||||
uci_write_config 0 ondemand "$CPU_MIN_FREQ" "$CPU_MAX_FREQ" 10 50
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@ -1,73 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ddns-scripts_aliyun
|
||||
PKG_VERSION:=1.0.3
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPLv2
|
||||
PKG_MAINTAINER:=Sense <sensec@gmail.com>
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ddns-scripts_aliyun
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=IP Addresses and Names
|
||||
TITLE:=DDNS extension for AliYun.com
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+ddns-scripts +wget-ssl +openssl-util
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/description
|
||||
Dynamic DNS Client scripts extension for AliYun.com
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(CP) ./*.sh $(PKG_BUILD_DIR)
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/preinst
|
||||
#!/bin/sh
|
||||
# if NOT run buildroot then stop service
|
||||
[ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/ddns $(1)/usr/share/ddns/default
|
||||
$(INSTALL_BIN) $(CURDIR)/update_aliyun_com.sh $(1)/usr/lib/ddns
|
||||
$(INSTALL_DATA) $(CURDIR)/aliyun.com.json $(1)/usr/share/ddns/default
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/postinst
|
||||
#!/bin/sh
|
||||
# remove old services file entries
|
||||
/bin/sed -i '/aliyun\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/aliyun\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
# and create new
|
||||
printf "%s\\t\\t%s\\n" '"aliyun.com"' '"update_aliyun_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services
|
||||
printf "%s\\t\\t%s\\n" '"aliyun.com"' '"update_aliyun_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services_ipv6
|
||||
# on real system restart service if enabled
|
||||
[ -z "$${IPKG_INSTROOT}" ] && {
|
||||
/etc/init.d/ddns enabled && \
|
||||
/etc/init.d/ddns start >/dev/null 2>&1
|
||||
}
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/prerm
|
||||
#!/bin/sh
|
||||
# if NOT run buildroot then stop service
|
||||
[ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1
|
||||
# remove services file entries
|
||||
/bin/sed -i '/aliyun\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/aliyun\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ddns-scripts_aliyun))
|
||||
@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "aliyun.com",
|
||||
"ipv4": {
|
||||
"url": "update_aliyun_com.sh"
|
||||
},
|
||||
"ipv6": {
|
||||
"url": "update_aliyun_com.sh"
|
||||
}
|
||||
}
|
||||
@ -1,248 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# 用于阿里云解析的DNS更新脚本
|
||||
# 2017-2018 Sense <sensec at gmail dot com>
|
||||
# 阿里云解析API文档 https://help.aliyun.com/document_detail/29739.html
|
||||
#
|
||||
# 本脚本由 dynamic_dns_functions.sh 内的函数 send_update() 调用
|
||||
#
|
||||
# 需要在 /etc/config/ddns 中设置的选项
|
||||
# option username - 阿里云API访问账号 Access Key ID。可通过 aliyun.com 帐号管理的 accesskeys 获取, 或者访问 https://ak-console.aliyun.com
|
||||
# option password - 阿里云API访问密钥 Access Key Secret
|
||||
# option domain - 完整的域名。建议主机与域名之间使用 @符号 分隔,否则将以第一个 .符号 之前的内容作为主机名
|
||||
#
|
||||
|
||||
# 检查传入参数
|
||||
[ -z "$username" ] && write_log 14 "配置错误!保存阿里云API访问账号的'用户名'不能为空"
|
||||
[ -z "$password" ] && write_log 14 "配置错误!保存阿里云API访问密钥的'密码'不能为空"
|
||||
|
||||
# 检查外部调用工具
|
||||
WGET_SSL='wget'
|
||||
[ -n "$WGET_SSL" ] || write_log 13 "使用阿里云API需要 GNU Wget 支持,请先安装"
|
||||
command -v sed >/dev/null 2>&1 || write_log 13 "使用阿里云API需要 sed 支持,请先安装"
|
||||
command -v openssl >/dev/null 2>&1 || write_log 13 "使用阿里云API需要 openssl-util 支持,请先安装"
|
||||
|
||||
# 包含用于解析 JSON 格式返回值的函数
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
# 变量声明
|
||||
local __HOST __DOMAIN __TYPE __URLBASE __CMDBASE __URLARGS __SEPARATOR __RECID
|
||||
[ $use_https -eq 0 ] && __URLBASE="http://alidns.aliyuncs.com/" || __URLBASE="https://alidns.aliyuncs.com/"
|
||||
__SEPARATOR="&"
|
||||
|
||||
# 从 $domain 分离主机和域名
|
||||
[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # 主域名处理
|
||||
[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # 未找到分隔符,兼容常用域名格式
|
||||
__HOST="${domain%%@*}"
|
||||
__DOMAIN="${domain#*@}"
|
||||
[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@"
|
||||
|
||||
# 设置记录类型
|
||||
[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA"
|
||||
|
||||
# 构造基本通信命令
|
||||
build_command() {
|
||||
__CMDBASE="$WGET_SSL --no-hsts -nv -t 1 -O $DATFILE -o $ERRFILE"
|
||||
# 绑定用于通信的主机/IP
|
||||
if [ -n "$bind_network" ]; then
|
||||
local bind_ip run_prog
|
||||
[ $use_ipv6 -eq 0 ] && run_prog="network_get_ipaddr" || run_prog="network_get_ipaddr6"
|
||||
eval "$run_prog bind_ip $bind_network" || \
|
||||
write_log 13 "无法使用 '$run_prog $bind_network' 获取本地IP地址 - 错误代码: '$?'"
|
||||
write_log 7 "强制使用IP '$bind_ip' 通信"
|
||||
__CMDBASE="$__CMDBASE --bind-address=$bind_ip"
|
||||
fi
|
||||
# 强制设定IP版本
|
||||
if [ $force_ipversion -eq 1 ]; then
|
||||
[ $use_ipv6 -eq 0 ] && __CMDBASE="$__CMDBASE -4" || __CMDBASE="$__CMDBASE -6"
|
||||
fi
|
||||
# 设置CA证书参数
|
||||
if [ $use_https -eq 1 ]; then
|
||||
if [ "$cacert" = "IGNORE" ]; then
|
||||
__CMDBASE="$__CMDBASE --no-check-certificate"
|
||||
elif [ -f "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-certificate=${cacert}"
|
||||
elif [ -d "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-directory=${cacert}"
|
||||
elif [ -n "$cacert" ]; then
|
||||
write_log 14 "在 '$cacert' 中未找到用于 HTTPS 通信的有效证书"
|
||||
fi
|
||||
fi
|
||||
# 如果没有设置,禁用代理 (这可能是 .wgetrc 或环境设置错误)
|
||||
[ -z "$proxy" ] && __CMDBASE="$__CMDBASE --no-proxy"
|
||||
}
|
||||
|
||||
# 用于阿里云API的通信函数
|
||||
aliyun_transfer() {
|
||||
local __PARAM=$*
|
||||
local __CNT=0
|
||||
local __RUNPROG __ERR PID_SLEEP
|
||||
|
||||
[ $# -eq 0 ] && write_log 12 "'aliyun_transfer()' 出错 - 参数数量错误"
|
||||
|
||||
while : ; do
|
||||
build_Request $__PARAM
|
||||
__RUNPROG="$__CMDBASE '${__URLBASE}?${__URLARGS}'"
|
||||
|
||||
write_log 7 "#> $__RUNPROG"
|
||||
eval $__RUNPROG
|
||||
__ERR=$?
|
||||
[ $__ERR -eq 0 ] && return 0
|
||||
|
||||
write_log 3 "wget 错误代码: '$__ERR'"
|
||||
write_log 7 "$(cat $ERRFILE)"
|
||||
|
||||
if [ $VERBOSE -gt 1 ]; then
|
||||
write_log 4 "传输失败 - 详细模式: $VERBOSE - 出错后不再重试"
|
||||
return 1
|
||||
fi
|
||||
|
||||
__CNT=$(( $__CNT + 1 ))
|
||||
[ $retry_count -gt 0 -a $__CNT -gt $retry_count ] && \
|
||||
write_log 14 "$retry_count 次重试后传输还是失败"
|
||||
|
||||
write_log 4 "传输失败 - $__CNT/$retry_count 在 $RETRY_SECONDS 秒后重试"
|
||||
sleep $RETRY_SECONDS &
|
||||
PID_SLEEP=$!
|
||||
wait $PID_SLEEP
|
||||
PID_SLEEP=0
|
||||
done
|
||||
}
|
||||
|
||||
# 百分号编码
|
||||
percentEncode() {
|
||||
if [ -z "${1//[A-Za-z0-9_.~-]/}" ]; then
|
||||
echo -n "$1"
|
||||
else
|
||||
local string=$1; local i=0; local ret chr
|
||||
while [ $i -lt ${#string} ]; do
|
||||
chr=${string:$i:1}
|
||||
[ -z "${chr#[^A-Za-z0-9_.~-]}" ] && chr=$(printf '%%%02X' "'$chr")
|
||||
ret="$ret$chr"
|
||||
i=$(( $i + 1 ))
|
||||
done
|
||||
echo -n "$ret"
|
||||
fi
|
||||
}
|
||||
|
||||
# 构造阿里云解析请求参数
|
||||
build_Request() {
|
||||
local args=$*; local string
|
||||
local HTTP_METHOD="GET"
|
||||
|
||||
# 添加请求参数
|
||||
__URLARGS=
|
||||
for string in $args; do
|
||||
case "${string%%=*}" in
|
||||
Format|TTL|Version|AccessKeyId|SignatureMethod|Timestamp|SignatureVersion|SignatureNonce|Signature) ;; # 过滤公共参数
|
||||
*) __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}");;
|
||||
esac
|
||||
done
|
||||
__URLARGS="${__URLARGS:1}"
|
||||
|
||||
# 附加公共参数
|
||||
string="Format=JSON"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="TTL=600";__URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="Version=2015-01-09"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="AccessKeyId=$username"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="SignatureMethod=HMAC-SHA1"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="Timestamp="$(date -u '+%Y-%m-%dT%H:%M:%SZ'); __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="SignatureVersion=1.0"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="SignatureNonce="$(cat '/proc/sys/kernel/random/uuid'); __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
|
||||
# 对请求参数进行排序,用于生成签名
|
||||
string=$(echo -n "$__URLARGS" | sed 's/\'"${__SEPARATOR}"'/\n/g' | sort | sed ':label; N; s/\n/\'"${__SEPARATOR}"'/g; b label')
|
||||
# 构造用于计算签名的字符串
|
||||
string="${HTTP_METHOD}${__SEPARATOR}"$(percentEncode "/")"${__SEPARATOR}"$(percentEncode "$string")
|
||||
# 字符串计算签名HMAC值
|
||||
local signature=$(echo -n "$string" | openssl dgst -sha1 -hmac "${password}&" -binary)
|
||||
# HMAC值编码成字符串,得到签名值
|
||||
signature=$(echo -n "$signature" | openssl base64)
|
||||
|
||||
# 附加签名参数
|
||||
string="Signature=$signature"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
}
|
||||
|
||||
# 添加解析记录
|
||||
add_domain() {
|
||||
local value
|
||||
aliyun_transfer "Action=AddDomainRecord" "DomainName=${__DOMAIN}" "RR=${__HOST}" "Type=${__TYPE}" "Value=${__IP}" || write_log 14 "服务器通信失败"
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_get_var value "RecordId"
|
||||
[ -z "$value" ] && write_log 14 "添加新解析记录失败"
|
||||
write_log 7 "添加新解析记录成功"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 修改解析记录
|
||||
update_domain() {
|
||||
local value
|
||||
aliyun_transfer "Action=UpdateDomainRecord" "RecordId=${__RECID}" "RR=${__HOST}" "Type=${__TYPE}" "Value=${__IP}" || write_log 14 "服务器通信失败"
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_get_var value "RecordId"
|
||||
[ -z "$value" ] && write_log 14 "修改解析记录失败"
|
||||
write_log 7 "修改解析记录成功"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 启用解析记录
|
||||
enable_domain() {
|
||||
local value
|
||||
aliyun_transfer "Action=SetDomainRecordStatus" "RecordId=${__RECID}" "Status=Enable" || write_log 14 "服务器通信失败"
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_get_var value "Status"
|
||||
[ "$value" != "Enable" ] && write_log 14 "启用解析记录失败"
|
||||
write_log 7 "启用解析记录成功"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 获取子域名解析记录列表
|
||||
describe_domain() {
|
||||
local count value; local ret=0
|
||||
aliyun_transfer "Action=DescribeSubDomainRecords" "SubDomain=${__HOST}.${__DOMAIN}" "DomainName=${__DOMAIN}" "Line=default" || write_log 14 "服务器通信失败"
|
||||
write_log 7 "获取到解析记录: $(cat "$DATFILE" 2> /dev/null)"
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_get_var count "TotalCount"
|
||||
if [ $count -eq 0 ]; then
|
||||
write_log 7 "解析记录不存在"
|
||||
ret=1
|
||||
else
|
||||
local i=1;
|
||||
while [ $i -le $count ]; do
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_select "DomainRecords" >/dev/null 2>&1
|
||||
json_select "Record" >/dev/null 2>&1
|
||||
json_select $i >/dev/null 2>&1
|
||||
i=$(( $i + 1 ))
|
||||
json_get_var value "Type"
|
||||
if [ "$value" != "${__TYPE}" ]; then
|
||||
write_log 7 "当前解析类型: ${__TYPE}, 获得不匹配类型: $value"
|
||||
ret=1; continue
|
||||
else
|
||||
ret=0
|
||||
json_get_var __RECID "RecordId"
|
||||
write_log 7 "获得解析记录ID: ${__RECID}, 类型: $value"
|
||||
json_get_var value "Locked"
|
||||
[ $value -ne 0 ] && write_log 14 "解析记录被锁定"
|
||||
json_get_var value "Status"
|
||||
[ "$value" != "ENABLE" ] && ret=$(( $ret | 2 )) && write_log 7 "解析记录被禁用"
|
||||
json_get_var value "Value"
|
||||
[ "$value" != "${__IP}" ] && ret=$(( $ret | 4 )) && write_log 7 "地址需要修改"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
return $ret
|
||||
}
|
||||
|
||||
build_command
|
||||
describe_domain
|
||||
ret=$?
|
||||
if [ $ret -eq 1 ]; then
|
||||
sleep 3 && add_domain
|
||||
else
|
||||
[ $(( $ret & 2 )) -ne 0 ] && sleep 3 && enable_domain
|
||||
[ $(( $ret & 4 )) -ne 0 ] && sleep 3 && update_domain
|
||||
fi
|
||||
|
||||
return 0
|
||||
@ -1,78 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ddns-scripts_dnspod
|
||||
PKG_VERSION:=1.0.2
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPLv2
|
||||
PKG_MAINTAINER:=Small_5
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ddns-scripts_dnspod
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=IP Addresses and Names
|
||||
TITLE:=DDNS extension for Dnspod.com/Dnspod.cn
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+ddns-scripts +wget-ssl +ca-bundle
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/description
|
||||
Dynamic DNS Client scripts extension for Dnspod.com/Dnspod.cn
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/preinst
|
||||
#!/bin/sh
|
||||
# if NOT run buildroot then stop service
|
||||
[ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/ddns $(1)/usr/share/ddns/default
|
||||
$(INSTALL_BIN) $(CURDIR)/*.sh $(1)/usr/lib/ddns
|
||||
$(INSTALL_DATA) $(CURDIR)/*.json $(1)/usr/share/ddns/default
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/postinst
|
||||
#!/bin/sh
|
||||
# remove old services file entries
|
||||
/bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
# and create new
|
||||
printf "%s\\t\\t%s\\n" '"dnspod.com"' '"update_dnspod_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services
|
||||
printf "%s\\t\\t%s\\n" '"dnspod.cn"' '"update_dnspod_cn.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services
|
||||
printf "%s\\t\\t%s\\n" '"dnspod.com"' '"update_dnspod_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services_ipv6
|
||||
printf "%s\\t\\t%s\\n" '"dnspod.cn"' '"update_dnspod_cn.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services_ipv6
|
||||
# on real system restart service if enabled
|
||||
[ -z "$${IPKG_INSTROOT}" ] && {
|
||||
/etc/init.d/ddns enabled && \
|
||||
/etc/init.d/ddns start >/dev/null 2>&1
|
||||
}
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/prerm
|
||||
#!/bin/sh
|
||||
# if NOT run buildroot then stop service
|
||||
[ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1
|
||||
# remove services file entries
|
||||
/bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ddns-scripts_dnspod))
|
||||
@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "dnspod.com",
|
||||
"ipv4": {
|
||||
"url": "update_dnspod_cn.sh"
|
||||
},
|
||||
"ipv6": {
|
||||
"url": "update_dnspod_cn.sh"
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "dnspod.com",
|
||||
"ipv4": {
|
||||
"url": "update_dnspod_com.sh"
|
||||
},
|
||||
"ipv6": {
|
||||
"url": "update_dnspod_com.sh"
|
||||
}
|
||||
}
|
||||
@ -1,155 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#检查传入参数
|
||||
[ -z "$username" ] && write_log 14 "Configuration error! [User name] cannot be empty"
|
||||
[ -z "$password" ] && write_log 14 "Configuration error! [Password] cannot be empty"
|
||||
|
||||
#检查外部调用工具
|
||||
WGET_SSL='wget'
|
||||
[ -n "$WGET_SSL" ] || write_log 13 "GNU Wget support is required to use dnspod API. Please install first"
|
||||
|
||||
# 变量声明
|
||||
local __URLBASE __HOST __DOMAIN __TYPE __CMDBASE __POST __POST1 __RECIP __RECID __value __TTL
|
||||
__URLBASE="https://dnsapi.cn/"
|
||||
|
||||
# 从 $domain 分离主机和域名
|
||||
[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # 主域名处理
|
||||
[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # 未找到分隔符,兼容常用域名格式
|
||||
__HOST="${domain%%@*}"
|
||||
__DOMAIN="${domain#*@}"
|
||||
[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@"
|
||||
|
||||
# 设置记录类型
|
||||
[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA"
|
||||
|
||||
# 构造基本通信命令
|
||||
build_command() {
|
||||
__CMDBASE="$WGET_SSL --no-hsts -nv -t 1 -O $DATFILE -o $ERRFILE"
|
||||
# 绑定用于通信的主机/IP
|
||||
if [ -n "$bind_network" ]; then
|
||||
local bind_ip run_prog
|
||||
[ $use_ipv6 -eq 0 ] && run_prog="network_get_ipaddr" || run_prog="network_get_ipaddr6"
|
||||
eval "$run_prog bind_ip $bind_network" || \
|
||||
write_log 13 "Unable to get local IP address with '$run_prog $ bind_network' - error code: '$?'"
|
||||
write_log 7 "Forced use of IP '$bind_ip' communication"
|
||||
__CMDBASE="$__CMDBASE --bind-address=$bind_ip"
|
||||
fi
|
||||
# 强制设定IP版本
|
||||
if [ $force_ipversion -eq 1 ]; then
|
||||
[ $use_ipv6 -eq 0 ] && __CMDBASE="$__CMDBASE -4" || __CMDBASE="$__CMDBASE -6"
|
||||
fi
|
||||
# 设置CA证书参数
|
||||
if [ $use_https -eq 1 ]; then
|
||||
if [ "$cacert" = "IGNORE" ]; then
|
||||
__CMDBASE="$__CMDBASE --no-check-certificate"
|
||||
elif [ -f "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-certificate=${cacert}"
|
||||
elif [ -d "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-directory=${cacert}"
|
||||
elif [ -n "$cacert" ]; then
|
||||
write_log 14 "A valid certificate for HTTPS communication was not found in '$cacert'"
|
||||
fi
|
||||
fi
|
||||
# 如果没有设置,禁用代理 (这可能是 .wgetrc 或环境设置错误)
|
||||
[ -z "$proxy" ] && __CMDBASE="$__CMDBASE --no-proxy"
|
||||
__CMDBASE="$__CMDBASE --post-data"
|
||||
}
|
||||
|
||||
# 用于Dnspod API的通信函数
|
||||
dnspod_transfer() {
|
||||
local __A=$1
|
||||
local __CNT=0
|
||||
local __ERR=0
|
||||
local __B PID_SLEEP
|
||||
case "$__A" in
|
||||
0)
|
||||
__B="$__CMDBASE '$__POST' ${__URLBASE}Record.List"
|
||||
;;
|
||||
1)
|
||||
__B="$__CMDBASE '$__POST1' ${__URLBASE}Record.Create"
|
||||
;;
|
||||
2)
|
||||
__B="$__CMDBASE '$__POST1&record_id=$__RECID&ttl=$__TTL' ${__URLBASE}Record.Modify"
|
||||
;;
|
||||
esac
|
||||
|
||||
while : ; do
|
||||
write_log 7 "#> $__B"
|
||||
eval $__B
|
||||
__ERR=`jsonfilter -i $DATFILE -e "@.status.code"`
|
||||
|
||||
[ $__ERR -eq 1 ] && return 0
|
||||
[ $__A -eq 0 ] && [ $__ERR -eq 10 ] && return 0
|
||||
write_log 3 "Error message:[$(jsonfilter -i $DATFILE -e "@.status.message")]"
|
||||
|
||||
if [ $VERBOSE -gt 1 ]; then
|
||||
write_log 4 "Transfer failed - detailed mode: $VERBOSE - Do not try again after an error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
__CNT=$(( $__CNT + 1 ))
|
||||
[ $retry_count -gt 0 -a $__CNT -gt $retry_count ] && write_log 14 "Transfer failed after $retry_count retries"
|
||||
|
||||
write_log 4 "Transfer failed - $__CNT Try again in $RETRY_SECONDS seconds"
|
||||
sleep $RETRY_SECONDS &
|
||||
PID_SLEEP=$!
|
||||
wait $PID_SLEEP
|
||||
PID_SLEEP=0
|
||||
done
|
||||
}
|
||||
|
||||
#添加解析记录
|
||||
add_domain() {
|
||||
dnspod_transfer 1
|
||||
write_log 7 "Add new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP] successfully!"
|
||||
return 0
|
||||
}
|
||||
|
||||
#修改解析记录
|
||||
update_domain() {
|
||||
dnspod_transfer 2
|
||||
write_log 7 "Modify new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP],[TTL:$__TTL] successfully!"
|
||||
return 0
|
||||
}
|
||||
|
||||
#获取域名解析记录
|
||||
describe_domain() {
|
||||
ret=0
|
||||
__POST="login_token=$username,$password&format=json&domain=$__DOMAIN&sub_domain=$__HOST&record_type=$__TYPE"
|
||||
__POST1="$__POST&value=$__IP&record_type=$__TYPE&record_line_id=0"
|
||||
dnspod_transfer 0
|
||||
__TMP=`jsonfilter -i $DATFILE -e "@.records[@.type!='NS']"`
|
||||
__value=`jsonfilter -s "$__TMP" -e "@.name"`
|
||||
if [ "$__value" == "" ]; then
|
||||
write_log 7 "Parsing record:[${__HOST}.${__DOMAIN}] does not exist"
|
||||
ret=1
|
||||
else
|
||||
__RECID=`jsonfilter -s "$__TMP" -e "@.id"`
|
||||
__value=`jsonfilter -s "$__TMP" -e "@.type"`
|
||||
__TTL=`jsonfilter -s "$__TMP" -e "@.ttl"`
|
||||
write_log 7 "Get parsing recordID:[$__RECID]"
|
||||
if [ "$__value" != "$__TYPE" ]; then
|
||||
write_log 7 "Current parsing [type:$__TYPE], get mismatched [type:$__value]"
|
||||
write_log 7 "Address needs to be modified, local address:[$__IP]"
|
||||
ret=2
|
||||
else
|
||||
__RECIP=`jsonfilter -s "$__TMP" -e "@.value"`
|
||||
if [ "$__RECIP" != "$__IP" ]; then
|
||||
write_log 7 "Address needs to be modified, local address:[$__IP]"
|
||||
ret=2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
build_command
|
||||
describe_domain
|
||||
if [ $ret == 1 ];then
|
||||
sleep 3 && add_domain
|
||||
elif [ $ret == 2 ];then
|
||||
sleep 3 && update_domain
|
||||
else
|
||||
write_log 7 "Local IP:[$__IP] parsing records IP:[$__RECIP] address does not need to be modified"
|
||||
fi
|
||||
|
||||
return 0
|
||||
@ -1,155 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#检查传入参数
|
||||
[ -z "$username" ] && write_log 14 "Configuration error! [User name] cannot be empty"
|
||||
[ -z "$password" ] && write_log 14 "Configuration error! [Password] cannot be empty"
|
||||
|
||||
#检查外部调用工具
|
||||
WGET_SSL='wget'
|
||||
[ -n "$WGET_SSL" ] || write_log 13 "GNU Wget support is required to use dnspod API. Please install first"
|
||||
|
||||
# 变量声明
|
||||
local __URLBASE __HOST __DOMAIN __TYPE __CMDBASE __POST __POST1 __RECIP __RECID __value __TTL
|
||||
__URLBASE="https://api.dnspod.com/"
|
||||
|
||||
# 从 $domain 分离主机和域名
|
||||
[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # 主域名处理
|
||||
[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # 未找到分隔符,兼容常用域名格式
|
||||
__HOST="${domain%%@*}"
|
||||
__DOMAIN="${domain#*@}"
|
||||
[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@"
|
||||
|
||||
# 设置记录类型
|
||||
[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA"
|
||||
|
||||
# 构造基本通信命令
|
||||
build_command() {
|
||||
__CMDBASE="$WGET_SSL --no-hsts -nv -t 1 -O $DATFILE -o $ERRFILE"
|
||||
# 绑定用于通信的主机/IP
|
||||
if [ -n "$bind_network" ]; then
|
||||
local bind_ip run_prog
|
||||
[ $use_ipv6 -eq 0 ] && run_prog="network_get_ipaddr" || run_prog="network_get_ipaddr6"
|
||||
eval "$run_prog bind_ip $bind_network" || \
|
||||
write_log 13 "Unable to get local IP address with '$run_prog $ bind_network' - error code: '$?'"
|
||||
write_log 7 "Forced use of IP '$bind_ip' communication"
|
||||
__CMDBASE="$__CMDBASE --bind-address=$bind_ip"
|
||||
fi
|
||||
# 强制设定IP版本
|
||||
if [ $force_ipversion -eq 1 ]; then
|
||||
[ $use_ipv6 -eq 0 ] && __CMDBASE="$__CMDBASE -4" || __CMDBASE="$__CMDBASE -6"
|
||||
fi
|
||||
# 设置CA证书参数
|
||||
if [ $use_https -eq 1 ]; then
|
||||
if [ "$cacert" = "IGNORE" ]; then
|
||||
__CMDBASE="$__CMDBASE --no-check-certificate"
|
||||
elif [ -f "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-certificate=${cacert}"
|
||||
elif [ -d "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-directory=${cacert}"
|
||||
elif [ -n "$cacert" ]; then
|
||||
write_log 14 "A valid certificate for HTTPS communication was not found in '$cacert'"
|
||||
fi
|
||||
fi
|
||||
# 如果没有设置,禁用代理 (这可能是 .wgetrc 或环境设置错误)
|
||||
[ -z "$proxy" ] && __CMDBASE="$__CMDBASE --no-proxy"
|
||||
__CMDBASE="$__CMDBASE --post-data"
|
||||
}
|
||||
|
||||
# 用于Dnspod API的通信函数
|
||||
dnspod_transfer() {
|
||||
local __A=$1
|
||||
local __CNT=0
|
||||
local __ERR=0
|
||||
local __B PID_SLEEP
|
||||
case "$__A" in
|
||||
0)
|
||||
__B="$__CMDBASE '$__POST' ${__URLBASE}Record.List"
|
||||
;;
|
||||
1)
|
||||
__B="$__CMDBASE '$__POST1' ${__URLBASE}Record.Create"
|
||||
;;
|
||||
2)
|
||||
__B="$__CMDBASE '$__POST1&record_id=$__RECID&ttl=$__TTL' ${__URLBASE}Record.Modify"
|
||||
;;
|
||||
esac
|
||||
|
||||
while : ; do
|
||||
write_log 7 "#> $__B"
|
||||
eval $__B
|
||||
__ERR=`jsonfilter -i $DATFILE -e "@.status.code"`
|
||||
|
||||
[ $__ERR -eq 1 ] && return 0
|
||||
[ $__A -eq 0 ] && [ $__ERR -eq 10 ] && return 0
|
||||
write_log 3 "Error message:[$(jsonfilter -i $DATFILE -e "@.status.message")]"
|
||||
|
||||
if [ $VERBOSE -gt 1 ]; then
|
||||
write_log 4 "Transfer failed - detailed mode: $VERBOSE - Do not try again after an error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
__CNT=$(( $__CNT + 1 ))
|
||||
[ $retry_count -gt 0 -a $__CNT -gt $retry_count ] && write_log 14 "Transfer failed after $retry_count retries"
|
||||
|
||||
write_log 4 "Transfer failed - $__CNT Try again in $RETRY_SECONDS seconds"
|
||||
sleep $RETRY_SECONDS &
|
||||
PID_SLEEP=$!
|
||||
wait $PID_SLEEP
|
||||
PID_SLEEP=0
|
||||
done
|
||||
}
|
||||
|
||||
#添加解析记录
|
||||
add_domain() {
|
||||
dnspod_transfer 1
|
||||
write_log 7 "Add new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP] successfully!"
|
||||
return 0
|
||||
}
|
||||
|
||||
#修改解析记录
|
||||
update_domain() {
|
||||
dnspod_transfer 2
|
||||
write_log 7 "Modify new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP],[TTL:$__TTL] successfully!"
|
||||
return 0
|
||||
}
|
||||
|
||||
#获取域名解析记录
|
||||
describe_domain() {
|
||||
ret=0
|
||||
__POST="login_token=$username,$password&format=json&domain=$__DOMAIN&sub_domain=$__HOST&record_type=$__TYPE"
|
||||
__POST1="$__POST&value=$__IP&record_type=$__TYPE&record_line_id=0"
|
||||
dnspod_transfer 0
|
||||
__TMP=`jsonfilter -i $DATFILE -e "@.records[@.type!='NS']"`
|
||||
__value=`jsonfilter -s "$__TMP" -e "@.name"`
|
||||
if [ "$__value" == "" ]; then
|
||||
write_log 7 "Parsing record:[${__HOST}.${__DOMAIN}] does not exist"
|
||||
ret=1
|
||||
else
|
||||
__RECID=`jsonfilter -s "$__TMP" -e "@.id"`
|
||||
__value=`jsonfilter -s "$__TMP" -e "@.type"`
|
||||
__TTL=`jsonfilter -s "$__TMP" -e "@.ttl"`
|
||||
write_log 7 "Get parsing recordID:[$__RECID]"
|
||||
if [ "$__value" != "$__TYPE" ]; then
|
||||
write_log 7 "Current parsing [type:$__TYPE], get mismatched [type:$__value]"
|
||||
write_log 7 "Address needs to be modified, local address:[$__IP]"
|
||||
ret=2
|
||||
else
|
||||
__RECIP=`jsonfilter -s "$__TMP" -e "@.value"`
|
||||
if [ "$__RECIP" != "$__IP" ]; then
|
||||
write_log 7 "Address needs to be modified, local address:[$__IP]"
|
||||
ret=2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
build_command
|
||||
describe_domain
|
||||
if [ $ret == 1 ];then
|
||||
sleep 3 && add_domain
|
||||
elif [ $ret == 2 ];then
|
||||
sleep 3 && update_domain
|
||||
else
|
||||
write_log 7 "Local IP:[$__IP] parsing records IP:[$__RECIP] address does not need to be modified"
|
||||
fi
|
||||
|
||||
return 0
|
||||
@ -1,38 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2016-2023 GitHub
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=default-settings
|
||||
PKG_RELEASE:=$(COMMITCOUNT)
|
||||
PKG_LICENSE:=GPLv3
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/default-settings
|
||||
SECTION:=luci
|
||||
CATEGORY:=LuCI
|
||||
TITLE:=LuCI support for Default Settings
|
||||
PKGARCH:=all
|
||||
DEPENDS:= +luci-compat +@LUCI_LANG_zh-cn +@LUCI_LANG_zh_Hans +@LUCI_LANG_en
|
||||
endef
|
||||
|
||||
define Package/default-settings/description
|
||||
Language Support Packages.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/default-settings/install
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/zzz-default-settings $(1)/etc/uci-defaults/99-default-settings
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
|
||||
po2lmo ./po/zh-cn/default.po $(1)/usr/lib/lua/luci/i18n/default.zh-cn.lmo
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,default-settings))
|
||||
@ -1,65 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF
|
||||
set system.@system[0].timezone='CST-8'
|
||||
set system.@system[0].zonename='Asia/Shanghai'
|
||||
|
||||
delete system.ntp.server
|
||||
add_list system.ntp.server='ntp1.aliyun.com'
|
||||
add_list system.ntp.server='ntp.tencent.com'
|
||||
add_list system.ntp.server='ntp.ntsc.ac.cn'
|
||||
add_list system.ntp.server='time.apple.com'
|
||||
EOF
|
||||
uci commit system
|
||||
|
||||
rm -f /usr/lib/lua/luci/view/admin_status/index/mwan.htm
|
||||
rm -f /usr/lib/lua/luci/view/admin_status/index/upnp.htm
|
||||
rm -f /usr/lib/lua/luci/view/admin_status/index/ddns.htm
|
||||
rm -f /usr/lib/lua/luci/view/admin_status/index/minidlna.htm
|
||||
|
||||
rm -f /www/luci-static/resources/view/status/include/70_ddns.js
|
||||
rm -f /www/luci-static/resources/view/status/include/80_upnp.js
|
||||
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/aria2.lua
|
||||
sed -i 's/services/nas/g' /usr/lib/lua/luci/view/aria2/overview_status.htm
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/hd_idle.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/samba.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/samba4.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/minidlna.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/transmission.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/mjpg-streamer.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/p910nd.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/usb_printer.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/xunlei.lua
|
||||
sed -i 's/services/nas/g' /usr/lib/lua/luci/view/minidlna_status.htm
|
||||
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/share/luci/menu.d/luci-app-samba4.json
|
||||
|
||||
sed -i 's#downloads.openwrt.org#mirrors.tencent.com/lede#g' /etc/opkg/distfeeds.conf
|
||||
sed -i 's#downloads.openwrt.org#mirrors.tencent.com/lede#g' /etc/apk/repositories.d/distfeeds.list
|
||||
sed -i 's/root::0:0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow
|
||||
sed -i 's/root:::0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow
|
||||
|
||||
sed -i "s/# //g" /etc/opkg/distfeeds.conf
|
||||
sed -i '/helloworld/d' /etc/opkg/distfeeds.conf
|
||||
sed -i '/openwrt_luci/ { s/snapshots/releases\/18.06.9/g; }' /etc/opkg/distfeeds.conf
|
||||
|
||||
sed -i '/check_signature/d' /etc/opkg.conf
|
||||
|
||||
sed -i '/REDIRECT --to-ports 53/d' /etc/firewall.user
|
||||
|
||||
sed -i '/DISTRIB_REVISION/d' /etc/openwrt_release
|
||||
echo "DISTRIB_REVISION='R26.05.20'" >> /etc/openwrt_release
|
||||
sed -i '/DISTRIB_DESCRIPTION/d' /etc/openwrt_release
|
||||
echo "DISTRIB_DESCRIPTION='LEDE '" >> /etc/openwrt_release
|
||||
|
||||
sed -i '/OPENWRT_RELEASE/d' /usr/lib/os-release
|
||||
echo 'OPENWRT_RELEASE="LEDE R26.05.20"' >> /usr/lib/os-release
|
||||
|
||||
sed -i '/log-facility/d' /etc/dnsmasq.conf
|
||||
echo "log-facility=/dev/null" >> /etc/dnsmasq.conf
|
||||
|
||||
rm -rf /tmp/luci-modulecache/
|
||||
rm -f /tmp/luci-indexcache
|
||||
|
||||
exit 0
|
||||
@ -1,70 +0,0 @@
|
||||
msgid "Swap"
|
||||
msgstr "虚拟内存"
|
||||
|
||||
msgid "Processor"
|
||||
msgstr "处理器"
|
||||
|
||||
msgid "Architecture"
|
||||
msgstr "架构"
|
||||
|
||||
msgid "CPU Temperature"
|
||||
msgstr "CPU 温度"
|
||||
|
||||
msgid "CPU Info"
|
||||
msgstr "CPU 信息"
|
||||
|
||||
msgid "CPU Model"
|
||||
msgstr "处理器型号"
|
||||
|
||||
msgid "CPU usage"
|
||||
msgstr "CPU 使用率"
|
||||
|
||||
msgid "CPU frequency"
|
||||
msgstr "CPU 频率"
|
||||
|
||||
msgid "RAM frequency"
|
||||
msgstr "RAM 频率"
|
||||
|
||||
msgid "Flash Size"
|
||||
msgstr "闪存大小"
|
||||
|
||||
msgid "Free Memory"
|
||||
msgstr "释放内存"
|
||||
|
||||
msgid "RUNNING"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "NOT RUNNING"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "ZRam Settings"
|
||||
msgstr "ZRam 设置"
|
||||
|
||||
msgid "ZRam Compression Algorithm"
|
||||
msgstr "ZRam 压缩算法"
|
||||
|
||||
msgid "ZRam Compression Streams"
|
||||
msgstr "ZRam 压缩数据流线程数"
|
||||
|
||||
msgid "ZRam Size"
|
||||
msgstr "ZRam 大小"
|
||||
|
||||
msgid "Size of the ZRam device in megabytes"
|
||||
msgstr "划分给 ZRam 分区的内存大小(MB),推荐留空由系统自动管理"
|
||||
|
||||
msgid "Number of parallel threads used for compression"
|
||||
msgstr "用于压缩内存数据的CPU并发线程数"
|
||||
|
||||
msgid "Force 40MHz mode"
|
||||
msgstr "强制 40MHz 频宽"
|
||||
|
||||
msgid ""
|
||||
"Always use 40MHz channels even if the secondary channel overlaps. Using this "
|
||||
"option does not comply with IEEE 802.11n-2009!"
|
||||
msgstr "强制启用 40MHz 频宽并忽略辅助信道重叠。此选项可能不兼容某些无线硬件导致无法启用!"
|
||||
|
||||
msgid "Disassociate On Low Acknowledgement"
|
||||
msgstr "弱信号剔除"
|
||||
|
||||
msgid "Allow AP mode to disconnect STAs based on low ACK condition"
|
||||
msgstr "允许 AP 模式基于低 ACK 条件判断剔除弱信号的客户端"
|
||||
@ -1,42 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015-2016 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=dsmboot
|
||||
PKG_VERSION:=5.2
|
||||
PKG_RELEASE:=5967.1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/dsmboot
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Synology DSM pxeboot from TFTP
|
||||
DEPENDS:=
|
||||
endef
|
||||
|
||||
define Package/dsmboot/description
|
||||
DSM 5.2 boot from TFTP
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/dsmboot/install
|
||||
$(INSTALL_DIR) $(1)/root
|
||||
$(INSTALL_DATA) ./files/* $(1)/root/
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/dsmboot $(1)/etc/uci-defaults/yyy-dsmboot
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,dsmboot))
|
||||
Binary file not shown.
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
set dhcp.@dnsmasq[0].enable_tftp='1'
|
||||
set dhcp.@dnsmasq[0].dhcp_boot='pxelinux.0'
|
||||
set dhcp.@dnsmasq[0].tftp_root='/root'
|
||||
commit dhcp
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
@ -1,9 +0,0 @@
|
||||
default 0
|
||||
timeout 0
|
||||
fallback 0
|
||||
|
||||
title Synology DSM
|
||||
map --mem (pd)/dsm.iso (hd32)
|
||||
map --hook
|
||||
chainloader (hd32)
|
||||
|
||||
Binary file not shown.
@ -1,53 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
PKG_NAME:=fogvdn
|
||||
PKG_VERSION:=1
|
||||
PKG_RELEASE:=1
|
||||
PKG_HASH:=skip
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
PKG_ARCH:=X64
|
||||
else ifeq ($(ARCH),arm)
|
||||
PKG_ARCH:=ARM
|
||||
else ifeq ($(ARCH),aarch64)
|
||||
PKG_ARCH:=ARM64
|
||||
endif
|
||||
|
||||
PKG_SOURCE:=fogvdn_PEAR_$(PKG_ARCH)_LINUX_latest.tar.gz
|
||||
PKG_SOURCE_URL:=https://download.openfogos.com/release/
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
PKG_UNPACK:=$(HOST_TAR) -C $(PKG_BUILD_DIR)/root --strip-components=1 -xzf $(DL_DIR)/$(PKG_SOURCE)
|
||||
|
||||
define Package/fogvdn
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=OpenFog Pear P2P CDN
|
||||
DEPENDS:=@(aarch64||arm||x86_64) \
|
||||
+bash +getopt +jq +ntpdate +whereis \
|
||||
+smartmontools +zoneinfo-all +coreutils \
|
||||
+coreutils-install +coreutils-df +coreutils-nohup
|
||||
endef
|
||||
|
||||
define Package/fogvdn/description
|
||||
OpenFog Pear Peer-to-Peer Content Delivery Network
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)/root
|
||||
$(PKG_UNPACK)
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/fogvdn/install
|
||||
$(CP) $(PKG_BUILD_DIR)/root/* $(1)/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,fogvdn))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user