diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | error_utils.c | 6 | ||||
-rw-r--r-- | error_utils.h | 3 | ||||
-rw-r--r-- | nicutils.c | 258 | ||||
-rw-r--r-- | nicutils.h | 21 | ||||
-rw-r--r-- | parser.c | 29 |
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_ */ @@ -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; |