summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--error_utils.c6
-rw-r--r--error_utils.h3
-rw-r--r--nicutils.c258
-rw-r--r--nicutils.h21
-rw-r--r--parser.c29
6 files changed, 317 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9155bb3..5138bfa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
find_package(Glib)
find_package(GIO)
include_directories(${GLIB_PKG_INCLUDE_DIRS})
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -funsigned-char -Wall")
add_executable(instr-daemon instr-daemon.c
signalobject.c
response.c
@@ -17,6 +17,7 @@ add_executable(instr-daemon instr-daemon.c
i2c.c
lcd.c
flash.c
+ nicutils.c
dummy_functions.c
)
add_executable(instr-client instr-client.c)
diff --git a/error_utils.c b/error_utils.c
index c4eae61..e6adb6e 100644
--- a/error_utils.c
+++ b/error_utils.c
@@ -57,6 +57,7 @@ void set_gpib_error_flags (int error_num)
case CalibrationPolarityError:
case Soft_Limit_Exceeded:
case SelfCalError:
+ case NetworkNotFound:
GPIB_Set_Device_Dependent_Error();
break;
default:
@@ -494,6 +495,11 @@ void get_error_text(gchar **response, int error_num)
format_error_text(response,-222,"Incorrect old password, or new password is too long or short. ");
break;
+ case NetworkNotFound:
+ format_error_text(response,-240,"Network not found.");
+ break;
+
+
default:
format_error_text(response,-200,"Specific problem unknown.");
}
diff --git a/error_utils.h b/error_utils.h
index a72dc90..ac9a8c9 100644
--- a/error_utils.h
+++ b/error_utils.h
@@ -73,6 +73,7 @@
#define peak_power_limit 71
#define average_power_limit 72
#define SelfCalError 73
+#define NetworkNotFound 74
// BEGIN CUSTOM DEFINES
#define LCD_cols 32
@@ -85,4 +86,4 @@ void queue_error_from_parser(gchar** response, int error_num);
void queue_error_and_get_text(gchar** response, int error_num);
void Error_Remove_From_Queue(void);
-#endif \ No newline at end of file
+#endif
diff --git a/nicutils.c b/nicutils.c
new file mode 100644
index 0000000..4396858
--- /dev/null
+++ b/nicutils.c
@@ -0,0 +1,258 @@
+/*
+ * nicutils.c
+ *
+ * Created on: 16 Aug 2012
+ * Author: daniel
+ */
+
+#include "nicutils.h"
+
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/if_ether.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <netinet/ether.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define BUFSIZE 8192
+
+static int netlink_createsock()
+{
+ return socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+}
+
+static int netlink_sendmessage(int sock, struct nlmsghdr* msg)
+{
+ return send(sock, msg, msg->nlmsg_len, 0);
+}
+
+static int netlink_readsock(int sockFd, char *bufPtr, int seqNum, int pId, int buffsize)
+{
+
+ struct nlmsghdr *nlHdr;
+ int readLen = 0, msgLen = 0;
+
+ do {
+ /* Receive response from the kernel */
+ if ((readLen = recv(sockFd, bufPtr, buffsize - msgLen, 0)) < 0) {
+ return -1;
+ }
+
+ nlHdr = (struct nlmsghdr *) bufPtr;
+
+ /* Check if the header is valid */
+ if ((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) {
+ return -1;
+ }
+
+ /* Check if the its the last message */
+ if (nlHdr->nlmsg_type == NLMSG_DONE) {
+ break;
+ }
+
+ else {
+ /* Else move the pointer to buffer appropriately */
+ bufPtr += readLen;
+ msgLen += readLen;
+ }
+
+ /* Check if its a multi part message */
+ if ((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) {
+ break;
+ }
+ } while ((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));
+
+ return msgLen;
+}
+
+static bool route_finddefault(struct nlmsghdr *nlHdr, char* ifname)
+{
+
+ // unwrap the data
+ struct rtmsg* rtMsg = (struct rtmsg *) NLMSG_DATA(nlHdr);
+
+ /* If the route is not for AF_INET or does not belong to main routing table
+ then return. */
+ if ((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) {
+ return NULL;
+ }
+
+ /* get the rtattr field */
+ struct rtattr* rtAttr = (struct rtattr *) RTM_RTA(rtMsg);
+
+ int rtLen = RTM_PAYLOAD(nlHdr);
+
+ // the idea here is that this doesn't get touched if the
+ // dst is 0 as the response doesn't contain an RTA_DST attribute
+ u_int dst = 0;
+
+ // bash through the attributes
+ for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) {
+ switch (rtAttr->rta_type) {
+ case RTA_OIF:
+ if_indextoname(*(int *) RTA_DATA(rtAttr), ifname);
+ break;
+ case RTA_DST:
+ dst = *((u_int*) RTA_DATA(rtAttr));
+ break;
+ }
+ // We already know we don't want this route, so get out of here
+ if (dst != 0) {
+ break;
+ }
+ }
+
+ return dst == 0;
+}
+
+static char* route_defaultrouteint()
+{
+
+ int sock, len, msgSeq = 0;
+
+ /* Create Socket */
+ if ((sock = netlink_createsock()) < 0) {
+ goto exit;
+ }
+
+ /* Initialize the buffer */
+ char* msgBuf = calloc(BUFSIZE, 1);
+ if (msgBuf == NULL) {
+ goto exit;
+ }
+
+ /* point the header and the msg structure pointers into the buffer */
+ struct nlmsghdr* nlMsg = (struct nlmsghdr *) msgBuf;
+ struct rtmsg* rtMsg = (struct rtmsg *) NLMSG_DATA(nlMsg);
+
+ /* Fill in the nlmsg header*/
+ nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
+ nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table .
+ nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.
+ nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet.
+ nlMsg->nlmsg_pid = getpid(); // PID of process sending the request.
+
+ /* Send the request */
+ if (netlink_sendmessage(sock, nlMsg) < 0) {
+ goto exit;
+ }
+
+ /* Read the response */
+ if ((len = netlink_readsock(sock, msgBuf, msgSeq, getpid(), BUFSIZE)) < 0) {
+ goto exit;
+ }
+
+ static char ifname[256];
+ for (; NLMSG_OK(nlMsg,len); nlMsg = NLMSG_NEXT(nlMsg,len)) {
+ if (route_finddefault(nlMsg, ifname)) {
+ break;
+ }
+ }
+
+exit:
+
+ if (sock >= 0) {
+ close(sock);
+ }
+
+ if (msgBuf != NULL) {
+ free(msgBuf);
+ }
+
+ return ifname;
+}
+
+static bool nicutils_info(char* intefacename, nicinfo* result)
+{
+
+ bool ret = false;
+
+ // get a socket to do the ioctl requests with
+ int sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ goto exit;
+ }
+
+ // setup an ifconf struct, allocate a buffer for the data and get
+ // all of the interfaces attached to the system that are up
+ struct ifconf interfaces;
+ interfaces.ifc_len = sizeof(struct ifreq) * 32; // enough space for 32 interfaces.. more than enough
+ interfaces.ifc_buf = malloc(interfaces.ifc_len);
+ if (ioctl(sock, SIOCGIFCONF, &interfaces) < 0) {
+ goto exit;
+ }
+
+ struct ifreq *ifr = interfaces.ifc_req;
+ int i;
+ for (i = 0; i < interfaces.ifc_len / sizeof(struct ifreq); i++) {
+ // is this the interface we want?
+ if (strcmp(ifr[i].ifr_name, intefacename) != 0) {
+ continue; // skip over this one
+ }
+
+ // get the address
+ struct sockaddr* addr = &(ifr[i].ifr_addr);
+
+ // handle ipv4 and ipv6 addresses..
+ switch (addr->sa_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &(((struct sockaddr_in *) addr)->sin_addr), result->ip, INET6_ADDRSTRLEN);
+ break;
+
+ case AF_INET6:
+ inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) addr)->sin6_addr), result->ip, INET6_ADDRSTRLEN);
+ break;
+
+ default:
+ snprintf(result->ip, sizeof(result->ip), "shouldneverhappen");
+ break;
+ }
+
+ // get the mac address
+ if (ioctl(sock, SIOCGIFHWADDR, &ifr[i]) < 0) {
+ goto exit;
+ }
+
+ // turn it into a nice string
+ snprintf(result->mac, sizeof(result->mac), "%02x:%02x:%02x:%02x:%02x:%02x",
+ (unsigned char) ifr[i].ifr_hwaddr.sa_data[0],
+ (unsigned char) ifr[i].ifr_hwaddr.sa_data[1],
+ (unsigned char) ifr[i].ifr_hwaddr.sa_data[2],
+ (unsigned char) ifr[i].ifr_hwaddr.sa_data[3],
+ (unsigned char) ifr[i].ifr_hwaddr.sa_data[4],
+ (unsigned char) ifr[i].ifr_hwaddr.sa_data[5]);
+
+ ret = true;
+ break; // break out of the loop
+ }
+
+exit:
+ if (interfaces.ifc_buf != NULL) {
+ free(interfaces.ifc_buf);
+ }
+
+ return ret;
+}
+
+bool nicutils_infofordefaultroute(nicinfo* result)
+{
+
+ char* defaultroute = route_defaultrouteint();
+ if (defaultroute == NULL) {
+ return false;
+ }
+
+ return nicutils_info(defaultroute, result);
+}
diff --git a/nicutils.h b/nicutils.h
new file mode 100644
index 0000000..b72d073
--- /dev/null
+++ b/nicutils.h
@@ -0,0 +1,21 @@
+/*
+ * nicutils.h
+ *
+ * Created on: 16 Aug 2012
+ * Author: daniel
+ */
+
+#ifndef NICUTILS_H_
+#define NICUTILS_H_
+
+#include <stdbool.h>
+#include <netinet/in.h>
+
+typedef struct {
+ char ip[INET6_ADDRSTRLEN];
+ char mac[18];
+} nicinfo;
+
+bool nicutils_infofordefaultroute(nicinfo* result);
+
+#endif /* NICUTILS_H_ */
diff --git a/parser.c b/parser.c
index 40a6d74..43c40ac 100644
--- a/parser.c
+++ b/parser.c
@@ -11,6 +11,7 @@ END DESCRIPTION **********************************************************/
#include "parser.h"
#include "flash.h"
+#include "nicutils.h"
#include <glib/gprintf.h>
//STATICS
@@ -45,7 +46,7 @@ static int Go_int_eprom_48(gchar** response, int channel, char *loc_string,char
static int Go_Float_eprom51(gchar** response, int channel, char *loc_string,char *store_string,int command_type);
static int Go_char_eprom_70(gchar** response, int channel, char *loc_string,char *store_string,int command_type);
static int Go_eprom_siz_86(gchar** response, int channel, int command_type);
-
+static int Go_sys_net_91(gchar** response, int channel, char *loc_string,char *store_string,int command_type);
static int Parser_id_word(char *id_me, int *channel, int *with_id_code)
{
@@ -755,6 +756,11 @@ void Parser_main (char *raw_in, int interactive_terminal, void(*cbfunc)(gpointer
case 86:
error_num=Go_eprom_siz_86(&response,channel,command_type);
break;
+
+ case 91:
+ error_num=Go_sys_net_91(&response,channel,parameter,units,command_type);
+ break;
+
case 9999:
// was only whitespace, ignore
break;
@@ -1034,6 +1040,27 @@ static int Go_eprom_siz_86(gchar** response, int channel, int command_type)
}
+static int Go_sys_net_91(gchar **response, int channel, char *loc_string,char *store_string,int command_type)
+{
+ nicinfo info;
+
+ switch (command_type) {
+ case query_simple:
+ if (nicutils_infofordefaultroute(&info)) {
+ *response = g_strdup_printf ("MAC address: %s, IP address: %s", info.mac, info.ip);
+ return OK;
+ } else {
+ return NetworkNotFound;
+ }
+ break;
+
+ default:
+ return SyntaxError;
+ break;
+ }
+}
+
+
static int Handle_Units(float *mult,char *units, char *in_base)
{
int len_base, len_all, pos;