X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=lib%2Fsrc%2Fnetwork.c;h=e10659620a2b765639c00aa3947b43af2cc7d0e1;hb=37f89190b48ac9b483286caa0534fba00bb6f7a9;hp=0306d0aa5462601489b8770b71298069a6b87973;hpb=8af9e22649c04b6fbd8d30ccbb86c7150623a102;p=ngadmin diff --git a/lib/src/network.c b/lib/src/network.c index 0306d0a..e106596 100644 --- a/lib/src/network.c +++ b/lib/src/network.c @@ -9,8 +9,10 @@ #include #include -#include -#include +#include +#include +#include +#include #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: