]> git.sur5r.net Git - ngadmin/blobdiff - lib/src/ngadmin.c
Added chained makefiles.
[ngadmin] / lib / src / ngadmin.c
index d1e33d1cc566696faa6d9cf82c8a2ef64bd493ee..2cbb97e640b93f3ad9d441a8dc1d092c11126096 100644 (file)
@@ -268,7 +268,10 @@ int ngadmin_login (struct ngadmin *nga, int id) {
  
  attr=createEmptyList();
  pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
- if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+ if ( (ret=readRequest(nga, attr))==ERR_OK ) {
+  // login succeeded
+  // TODO: if keep broadcasting is disabled, connect() the UDP socket so icmp errors messages (port unreachable, TTL exceeded in transit, ...)can be received
+ } else {
   // login failed
   nga->current=NULL;
  }
@@ -589,7 +592,11 @@ int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
  List *attr;
  ListNode *ln;
  struct attr *at;
- int ret=ERR_OK, i;
+ int ret=ERR_OK;
+ struct {
+  char port;
+  int bitrate;
+ } __attribute__((packed)) *p;
  
  
  if ( nga==NULL || ports==NULL ) {
@@ -609,10 +616,12 @@ int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
  
  for (ln=attr->first; ln!=NULL; ln=ln->next) {
   at=ln->data;
-  if ( at->attr==ATTR_BITRATE_INPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
-   ports[i*2+0]=ntohl(*(int*)(1+(char*)at->data));
-  } else if ( at->attr==ATTR_BITRATE_OUTPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
-   ports[i*2+1]=ntohl(*(int*)(1+(char*)at->data));
+  p=at->data;
+  if ( at->size<sizeof(*p) || p->port<1 || p->port>nga->current->ports ) continue;
+  if ( at->attr==ATTR_BITRATE_INPUT ) {
+   ports[(p->port-1)*2+0]=ntohl(p->bitrate);
+  } else if ( at->attr==ATTR_BITRATE_OUTPUT ) {
+   ports[(p->port-1)*2+1]=ntohl(p->bitrate);
   }
  }
  
@@ -872,10 +881,10 @@ int ngadmin_getMirror (struct ngadmin *nga, char *ports) {
  for (ln=attr->first; ln!=NULL; ln=ln->next) {
   at=ln->data;
   p=at->data;
-  if ( at->attr==ATTR_MIRROR && at->size>=2+sa->ports/8 && p[0]<=nga->current->ports ) {
+  if ( at->attr==ATTR_MIRROR && at->size>=3 && p[0]<=nga->current->ports ) {
    ports[0]=p[0];
    for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
-    ports[i]=(p[2]>>(sa->ports-i))&1;
+    ports[i]=(p[2]>>(8-i))&1;
    }
    break;
   }
@@ -915,7 +924,7 @@ int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
   p[0]=ports[0];
   for (i=1; i<=sa->ports; ++i) {
    if ( i!=p[0] ) {
-    p[2]|=(ports[i]&1)<<(sa->ports-i);
+    p[2]|=(ports[i]&1)<<(8-i);
    }
   }
  }
@@ -953,7 +962,7 @@ int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) {
  ATTR_IGMP_BLOCK_UNK
  ATTR_IGMP_VALID_V3
  
- Apparently, read-querying theses attributes at the same time causes the switch to reply garbage. 
+ Apparently, read-querying these attributes at the same time causes the switch to reply garbage. 
  Here we are forced to do like the official win app and send a separate request for each attribute. 
  */
  
@@ -1118,3 +1127,403 @@ int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb) {
 
 
 
+// --------------------------------------------------------------------
+int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) {
+ List *attr;
+ struct swi_attr *sa;
+ int ret=ERR_OK;
+ if ( nga==NULL || nc==NULL ) {
+  return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+  return ERR_NOTLOG;
+ }
+ attr=createEmptyList();
+ if ( nc->dhcp ) {
+  pushBackList(attr, newByteAttr(ATTR_DHCP, 1));
+ } else {
+  pushBackList(attr, newByteAttr(ATTR_DHCP, 0));
+  // only add non-null values
+  if ( nc->ip.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
+  if ( nc->netmask.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
+  if ( nc->gw.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
+ }
+ if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
+  goto end;
+ }
+ // update local values
+ sa->nc.dhcp=nc->dhcp;
+ if ( !nc->dhcp ) {
+  if ( nc->ip.s_addr!=0 ) sa->nc.ip=nc->ip;
+  if ( nc->netmask.s_addr!=0 ) sa->nc.netmask=nc->netmask;
+  if ( nc->gw.s_addr!=0 ) sa->nc.gw=nc->gw;
+ }
+ end:
+ return ret;
+}
+
+
+
+// --------------------------------------------------
+int ngadmin_getVLANType (struct ngadmin *nga, int *t) {
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK;
+ if ( nga==NULL || t==NULL ) {
+  return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+  return ERR_NOTLOG;
+ }
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+  goto end;
+ }
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+  at=ln->data;
+  if ( at->attr==ATTR_VLAN_TYPE && at->size>=1 ) {
+   *t= (int)*(char*)at->data ;
+   break;
+  }
+ }
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+ return ret;
+}
+
+
+
+// -------------------------------------------------
+int ngadmin_setVLANType (struct ngadmin *nga, int t) {
+ List *attr;
+ struct swi_attr *sa;
+ if ( nga==NULL || t<1 || t>4 ) {
+  return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+  return ERR_NOTLOG;
+ }
+ attr=createEmptyList();
+ pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
+ return writeRequest(nga, attr);
+}
+
+
+
+// ------------------------------------------------------------------------------------------------------
+int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb) {
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ struct swi_attr *sa;
+ int ret=ERR_OK, total, i;
+ char *p=NULL;
+ if ( nga==NULL || vlans==NULL || ports==NULL || nb==NULL || *nb<=0 ) {
+  return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+  return ERR_NOTLOG;
+ }
+ total=*nb;
+ *nb=0;
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+  goto end;
+ }
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+  at=ln->data;
+  p=at->data;
+  if ( *nb>=total ) break; // no more room
+  if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
+   for (i=0; i<sa->ports; ++i) {
+    if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
+    else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
+    else ports[i]=VLAN_NO;
+   }
+   *vlans++=ntohs(*(unsigned short*)p);
+   ports+=sa->ports;
+   ++*nb;
+  }
+ }
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+ return ret;
+}
+
+
+
+// ----------------------------------------------------------------------------------------
+int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports) {
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ struct swi_attr *sa;
+ int ret=ERR_OK, i;
+ char *p=NULL;
+ if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
+  return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+  return ERR_NOTLOG;
+ }
+ attr=createEmptyList();
+ pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+  goto end;
+ }
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+  at=ln->data;
+  p=at->data;
+  if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
+   for (i=0; i<sa->ports; ++i) {
+    if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
+    else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
+    else ports[i]=VLAN_NO;
+   }
+   break;
+  }
+ }
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+ return ret;
+}
+
+
+
+// ----------------------------------------------------------------------------------------------
+int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports) {
+ List *attr=NULL;
+ ListNode *ln;
+ struct attr *at;
+ struct swi_attr *sa;
+ char *p, fl;
+ int ret=ERR_OK, i;
+ if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
+  return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+  return ERR_NOTLOG;
+ }
+ // if nothing is to be changed, do nothing
+ for (i=0; i<sa->ports && ports[i]==VLAN_UNSPEC; ++i);
+ if ( i==sa->ports ) goto end;
+ attr=createEmptyList();
+ p=malloc(4);
+ *(unsigned short*)p=htons(vlan);
+ *(unsigned short*)&p[2]=0;
+ // if all is to be changed, we do not need to read old config
+ if ( memchr(ports, VLAN_UNSPEC, sa->ports)!=NULL ) {
+  
+  attr=createEmptyList();
+  pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
+  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+   goto end;
+  }
+  
+  for (ln=attr->first; ln!=NULL; ln=ln->next) {
+   at=ln->data;
+   if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
+    *(unsigned short*)&p[2]=*(unsigned short*)(at->data+2);
+    break;
+   }
+  }
+  
+  clearList(attr, (void(*)(void*))freeAttr);
+  
+ }
+ // apply changes
+ for (i=0; i<sa->ports; ++i) {
+  fl=(1<<(7-i));
+  switch ( ports[i] ) {
+   case VLAN_NO:
+    p[2]&=~fl;
+    p[3]&=~fl;
+   break;
+   case VLAN_UNTAGGED:
+    p[2]|=fl;
+    p[3]&=~fl;
+   break;
+   case VLAN_TAGGED:
+    p[2]|=fl;
+    p[3]|=fl;
+  }
+ }
+ pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, 4, p));
+ ret=writeRequest(nga, attr);
+ attr=NULL;
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+ return ret;
+}
+
+
+
+// ---------------------------------------------------------------
+int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan) {
+ List *attr;
+ struct swi_attr *sa;
+ if ( nga==NULL || vlan<1 || vlan>VLAN_MAX ) {
+  return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+  return ERR_NOTLOG;
+ }
+ attr=createEmptyList();
+ pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
+ return writeRequest(nga, attr);
+}
+
+
+
+// ----------------------------------------------------------------
+int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports) {
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ struct swi_attr *sa;
+ int ret=ERR_OK;
+ char *p;
+ if ( nga==NULL || ports==NULL ) {
+  return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+  return ERR_NOTLOG;
+ }
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+  goto end;
+ }
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+  at=ln->data;
+  p=at->data;
+  if ( at->attr==ATTR_VLAN_PVID && at->size>=3 && p[0]>=1 && p[0]<=sa->ports ) {
+   ports[p[0]-1]=htons(*(unsigned short*)&p[1]);
+  }
+ }
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+ return ret;
+}
+
+
+
+// -------------------------------------------------------------------------------
+int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan) {
+ List *attr;
+ struct swi_attr *sa;
+ char *p;
+ if ( nga==NULL || port<1 || vlan<1 || vlan>VLAN_MAX ) {
+  return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+  return ERR_NOTLOG;
+ } else if ( port>sa->ports ) {
+  return ERR_INVARG;
+ }
+ attr=createEmptyList();
+ p=malloc(3);
+ p[0]=port;
+ *(unsigned short*)&p[1]=htons(vlan);
+ pushBackList(attr, newAttr(ATTR_VLAN_PVID, 3, p));
+ return writeRequest(nga, attr);;
+}
+
+
+