]> git.sur5r.net Git - ngadmin/blobdiff - lib/src/network.c
Raw: refactor attribute encoding and decoding
[ngadmin] / lib / src / network.c
index 0306d0aa5462601489b8770b71298069a6b87973..e10659620a2b765639c00aa3947b43af2cc7d0e1 100644 (file)
@@ -9,8 +9,10 @@
 #include <netinet/ether.h>
 #include <sys/ioctl.h>
 
-#include <attr.h>
-#include <protocol.h>
+#include <nsdp/attr.h>
+#include <nsdp/misc.h>
+#include <nsdp/net.h>
+#include <nsdp/protocol.h>
 
 #include "network.h"
 
@@ -30,16 +32,7 @@ int startNetwork (struct ngadmin *nga)
        
        memset(&ifr, 0, sizeof(struct ifreq));
        strncpy(ifr.ifr_name, nga->iface, IFNAMSIZ - 1);
-       
-       /* get the interface broadcast address */
-       ret = ioctl(nga->sock, SIOCGIFBRDADDR, &ifr);
-       if (ret < 0) {
-               perror("ioctl(SIOCGIFBRDADDR)");
-               close(nga->sock);
-               return ret;
-       }
-       nga->brd = (*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr;
-       
+
        /* get the interface MAC address */
        ret = ioctl(nga->sock, SIOCGIFHWADDR, &ifr);
        if (ret < 0) {
@@ -82,6 +75,36 @@ int startNetwork (struct ngadmin *nga)
 }
 
 
+int setBroadcastType (struct ngadmin *nga, bool value)
+{
+       int ret;
+       struct ifreq ifr;
+       
+       
+       nga->globalbroad = value;
+       if (value) {
+               nga->brd.s_addr = (in_addr_t)0;
+               return 0;
+       }
+       
+       memset(&ifr, 0, sizeof(struct ifreq));
+       strncpy(ifr.ifr_name, nga->iface, IFNAMSIZ - 1);
+       
+       /* get the interface broadcast address */
+       ret = ioctl(nga->sock, SIOCGIFBRDADDR, &ifr);
+       if (ret < 0) {
+               perror("ioctl(SIOCGIFBRDADDR)");
+               nga->brd.s_addr = (in_addr_t)0;
+               nga->globalbroad = true;
+               return ret;
+       }
+       
+       nga->brd = (*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr;
+       
+       return 0;
+}
+
+
 int stopNetwork (struct ngadmin *nga)
 {
        return close(nga->sock);
@@ -93,22 +116,20 @@ int forceInterface (struct ngadmin *nga)
        int ret;
        
        
-       /*
-       As described bellow, when you have multiple interfaces, this forces the packet 
-       to go to a particular interface. 
-       */
+       /* as described bellow, when you have multiple interfaces, this
+        * forces the packet to go to a particular interface
+        */
        ret = setsockopt(nga->sock, SOL_SOCKET, SO_BINDTODEVICE, nga->iface, strlen(nga->iface) + 1);
        if (ret < 0) {
                perror("setsockopt(SO_BINDTODEVICE)");
                return ret;
        }
        
-       /*
-       If the switch's IP is not in your network range, for instance because you do 
-       not have DHCP  enabled or you started the switch after it, this allows to 
-       bypass the routing tables and consider every address is directly reachable on 
-       the interface. 
-       */
+       /* if the switch's IP is not in your network range, for instance
+        * because you do not have DHCP  enabled or you started the switch
+        * after your DHCP server, this allows to bypass the routing tables
+        * and consider every address is directly reachable on the interface
+        */
        ret = 1;
        ret = setsockopt(nga->sock, SOL_SOCKET, SO_DONTROUTE, &ret, sizeof(ret));
        if (ret <0) {
@@ -121,133 +142,74 @@ int forceInterface (struct ngadmin *nga)
 }
 
 
-int updateTimeout (struct ngadmin *nga)
+static int checkErrorCode (const struct nsdp_cmd *nc)
 {
-       int ret;
+       switch (nc->error) {
        
+       case ERROR_DENIED:
+               return (nc->attr_error == ATTR_PASSWORD) ? ERR_BADPASS : ERR_DENIED;
        
-       /* specify receive timeout */
-       ret = setsockopt(nga->sock, SOL_SOCKET, SO_RCVTIMEO, &nga->timeout, sizeof(struct timeval));
-       if (ret < 0) {
-               perror("setsockopt(SO_RCVTIMEO)");
-               return ret;
-       }
-       
+       case ERROR_INVALID_VALUE:
+               return ERR_INVARG;
        
-       return 0;
+       default:
+               return ERR_OK;
+       }
 }
 
 
-int sendNgPacket (struct ngadmin *nga, char code, const List *attr)
+void prepareSend (struct ngadmin *nga, struct nsdp_cmd *nc, unsigned char code)
 {
-       char buffer[1500];
-       struct ng_packet np;
-       struct sockaddr_in remote;
-       const struct swi_attr *sa = nga->current;
-       int ret;
-       
-       
-       np.buffer = buffer;
-       np.maxlen = sizeof(buffer);
-       initNgPacket(&np);
-       initNgHeader(np.nh, code, &nga->localmac, sa == NULL ? NULL : &sa->mac, ++nga->seq);
+       struct swi_attr *sa = nga->current;
        
-       ret = addPacketAttributes(&np, attr, sa == NULL ? 0 : sa->ports);
-       if (ret < 0)
-               return ret;
        
-       memset(&remote, 0, sizeof(struct sockaddr_in));
-       remote.sin_family = AF_INET;
-       remote.sin_port = htons(SWITCH_PORT);
+       memset(nc, 0, sizeof(struct nsdp_cmd));
+       memcpy(&nc->client_mac, &nga->localmac, ETH_ALEN);
+       nc->remote_addr.sin_family = AF_INET;
+       nc->remote_addr.sin_port = htons(SWITCH_PORT);
+       if (sa != NULL)
+               memcpy(&nc->switch_mac, &sa->mac, ETH_ALEN);
        
        /* destination address selection */
        if (sa != NULL && !nga->keepbroad)
-               remote.sin_addr = sa->nc.ip;
+               nc->remote_addr.sin_addr = sa->nc.ip;
        else if (nga->globalbroad)
-               remote.sin_addr.s_addr = htonl(INADDR_BROADCAST);
+               nc->remote_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
        else
-               remote.sin_addr = nga->brd;
-       
-       ret = sendto(nga->sock, buffer, getPacketTotalSize(&np), 0, (struct sockaddr*)&remote, sizeof(struct sockaddr_in));
-       if (ret < 0)
-               perror("sendto");
-       
+               nc->remote_addr.sin_addr = nga->brd;
        
-       return ret;
+       nc->seqnum = ++nga->seq;
+       nc->code = code;
 }
 
 
-int recvNgPacket (struct ngadmin *nga, char code, unsigned char *error, unsigned short *attr_error, List *attr)
+void prepareRecv (struct ngadmin *nga, struct nsdp_cmd *nc, unsigned char code)
 {
-       char buffer[1500];
-       struct ng_packet np;
-       struct sockaddr_in remote;
-       socklen_t slen = sizeof(struct sockaddr_in);
-       const struct swi_attr *sa = nga->current;
-       struct timeval rem;
-       fd_set fs;
-       int len = -1;
-       
+       struct swi_attr *sa = nga->current;
        
-       np.buffer = buffer;
        
-       memset(&remote, 0, sizeof(struct sockaddr_in));
-       remote.sin_family = AF_INET;
-       
-       rem = nga->timeout;
-       
-       while (1) {
-               
-               FD_ZERO(&fs);
-               FD_SET(nga->sock, &fs);
-               select(nga->sock+1, &fs, NULL, NULL, &rem); /* FIXME: non portable */
-               
-               len = recvfrom(nga->sock, buffer, sizeof(buffer), MSG_DONTWAIT, (struct sockaddr*)&remote, &slen);
-               
-               if (len < 0)
-                       break;
-               
-               np.maxlen = len;
-               initNgPacket(&np);
-               
-               if (ntohs(remote.sin_port) != SWITCH_PORT ||
-                   len < (int)sizeof(struct ng_header) ||
-                   !validateNgHeader(np.nh, code, &nga->localmac, sa == NULL ? NULL : &sa->mac, nga->seq) ||
-                   extractPacketAttributes(&np, attr, sa == NULL ? 0 : sa->ports) < 0)
-                       continue;
-               
-               if (error != NULL)
-                       *error = np.nh->error;
-               if (attr_error != NULL)
-                       *attr_error = ntohs(np.nh->attr);
-               
-               len = 0;
-               break;
-       }
+       memset(nc, 0, sizeof(struct nsdp_cmd));
+       memcpy(&nc->client_mac, &nga->localmac, ETH_ALEN);
+       nc->remote_addr.sin_family = AF_INET;
+       nc->remote_addr.sin_port = htons(SWITCH_PORT);
+       if (sa != NULL)
+               memcpy(&nc->switch_mac, &sa->mac, ETH_ALEN);
        
+       /* set filter on switch IP */
+       if (sa == NULL)
+               nc->remote_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+       else
+               nc->remote_addr.sin_addr = sa->nc.ip;
        
-       return len;
-}
-
-
-static int checkErrorCode (unsigned char err, unsigned short attr_error)
-{
-       switch (err) {
-       case ERROR_DENIED:
-               return attr_error == ATTR_PASSWORD ? ERR_BADPASS : ERR_DENIED;
-       case ERROR_INVALID_VALUE:
-               return ERR_INVARG;
-       default:
-               return ERR_OK;
-       }
+       nc->seqnum = nga->seq;
+       nc->code = code;
 }
 
 
 int readRequest (struct ngadmin *nga, List *attr)
 {
        int i, ret = ERR_OK;
-       unsigned char err;
-       unsigned short attr_error;
+       struct nsdp_cmd nc;
        
        
        if (nga == NULL) {
@@ -258,25 +220,28 @@ int readRequest (struct ngadmin *nga, List *attr)
        /* add end attribute to end */
        pushBackList(attr, newEmptyAttr(ATTR_END));
        
-       i = sendNgPacket(nga, CODE_READ_REQ, attr);
+       prepareSend(nga, &nc, CODE_READ_REQ);
+       i = sendNsdpPacket(nga->sock, &nc, attr);
        
-       /* the list will be filled again by recvNgPacket */
+       /* do not destroy the list, it will be filled again later by recvNsdpPacket */
        clearList(attr, (void(*)(void*))freeAttr);
        
-       if (i >= 0)
-               i = recvNgPacket(nga, CODE_READ_REP, &err, &attr_error, attr);
+       if (i >= 0) {
+               prepareRecv(nga, &nc, CODE_READ_REP);
+               i = recvNsdpPacket(nga->sock, &nc, attr, &nga->timeout);
+       }
        
        if (i == -EINVAL) {
                ret = ERR_INVARG;
                goto end;
        } else if (i < 0) {
-               ret = ( errno == EAGAIN || errno == EWOULDBLOCK ) ? ERR_TIMEOUT : ERR_NET;
+               ret = (errno == EAGAIN || errno == EWOULDBLOCK) ? ERR_TIMEOUT : ERR_NET;
                goto end;
        }
        
        
        /* check the switch error code */
-       ret = checkErrorCode(err, attr_error);
+       ret = checkErrorCode(&nc);
        
        
 end:
@@ -287,9 +252,8 @@ end:
 int writeRequest (struct ngadmin *nga, List *attr)
 {
        int i, ret = ERR_OK;
-       unsigned char err;
-       unsigned short attr_error;
        struct attr *at;
+       struct nsdp_cmd nc;
        
        
        if (nga == NULL) {
@@ -313,25 +277,29 @@ int writeRequest (struct ngadmin *nga, List *attr)
        /* add end attribute to end */
        pushBackList(attr, newEmptyAttr(ATTR_END));
        
-       i = sendNgPacket(nga, CODE_WRITE_REQ, attr);
+       prepareSend(nga, &nc, CODE_WRITE_REQ);
+       i = sendNsdpPacket(nga->sock, &nc, attr);
        
        /* the list will be filled again by recvNgPacket
-       but normally it will be still empty */
+        * but normally it will be still empty
+        */
        clearList(attr, (void(*)(void*))freeAttr);
        
-       if (i >= 0)
-               i = recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, attr);
+       if (i >= 0) {
+               prepareRecv(nga, &nc, CODE_WRITE_REP);
+               i = recvNsdpPacket(nga->sock, &nc, attr, &nga->timeout);
+       }
        
        if (i == -EINVAL) {
                ret = ERR_INVARG;
                goto end;
        } else if (i < 0) {
-               ret = ( errno==EAGAIN || errno==EWOULDBLOCK ) ? ERR_TIMEOUT : ERR_NET ;
+               ret = (errno == EAGAIN || errno == EWOULDBLOCK) ? ERR_TIMEOUT : ERR_NET;
                goto end;
        }
        
        /* check the switch error code */
-       ret = checkErrorCode(err, attr_error);
+       ret = checkErrorCode(&nc);
        
        
 end: