]> git.sur5r.net Git - ngadmin/blob - emu.c
Initial commit.
[ngadmin] / emu.c
1
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <unistd.h>
7 #include <signal.h>
8 #include <arpa/inet.h>
9 #include <net/if.h>
10 #include <netinet/ether.h>
11 #include <sys/ioctl.h>
12
13 #include "protocol.h"
14
15
16
17
18 int sock;
19
20
21
22 __attribute__((noreturn)) void handler (int sig) {
23  
24  
25  if ( sig==SIGINT ) {
26   printf("\033[1G");
27  }
28  
29  
30  close(sock);
31  
32  
33  exit(0);
34  
35 }
36
37
38
39 int main (int argc, char **argv) {
40  
41  char buffer[1024];
42  socklen_t slen=sizeof(struct sockaddr_in);
43  struct sockaddr_in local, client;
44  struct ether_addr localmac;
45  struct in_addr localip;
46  struct ifreq ifr;
47  int len, i;
48  unsigned char ports=8;
49  struct ng_packet np;
50  struct attr *at;
51  List *l;
52  ListNode *ln;
53  
54  
55  
56  if ( argc<2 ) {
57   printf("Usage: %s <interface>\n", argv[0]);
58   return 1;
59  }
60  
61  memset(&local, 0, sizeof(struct sockaddr_in));
62  local.sin_family=AF_INET;
63  client=local;
64  local.sin_addr.s_addr=htonl(INADDR_ANY);
65  local.sin_port=htons(SWITCH_PORT);
66  
67  memset(&ifr, 0, sizeof(struct ifreq));
68  strncpy(ifr.ifr_name, argv[1], IFNAMSIZ-1);
69  
70  np.buffer=buffer;
71  np.maxlen=sizeof(buffer);
72  
73  if ( (sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))<0 ) {
74   perror("socket");
75  } else if ( bind(sock, (struct sockaddr*)&local, sizeof(struct sockaddr_in))<0 ) {
76   perror("bind");
77  }
78  
79  i=1;
80  if ( setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i))<0 ) {
81   perror("setsockopt(SO_BROADCAST)");
82  }
83  
84  /*
85  i=0;
86  if ( setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &i, sizeof(i)) ) {
87   perror("setsockopt(IP_MULTICAST_LOOP)");
88  }
89  */
90  
91  
92  if ( ioctl(sock, SIOCGIFHWADDR, &ifr)<0 ) {
93   perror("ioctl(SIOCGIFHWADDR)");
94  }
95  memcpy(&localmac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
96  
97  if ( ioctl(sock, SIOCGIFADDR, &ifr)<0 ) {
98   perror("ioctl(SIOCGIFADDR)");
99  }
100  localip=(*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr;
101  
102  
103  printf("server: ip %s, mac %s\n", inet_ntoa(localip), ether_ntoa(&localmac));
104  
105  signal(SIGINT, handler);
106  signal(SIGTERM, handler);
107  
108  
109  while ( 1 ) {
110   
111   if ( (len=recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&client, &slen))<0 ) {
112    perror("recvfrom");
113    break;
114   }
115   
116   if ( len<(int)sizeof(struct ng_header) || ( memcmp(&np.nh->switch_mac, &nullMac, 6)!=0 && memcmp(&np.nh->switch_mac, &localmac, 6)!=0 ) ) {
117    continue;
118   }
119   
120   printf("received %d bytes from %s: \n", len, inet_ntoa(client.sin_addr));
121   
122   printf("code: %i\n", np.nh->code);
123   printf("client mac: %s\n", ether_ntoa((struct ether_addr*)np.nh->client_mac));
124   printf("seq num: %d\n", ntohl(np.nh->seqnum));
125   printf("\n");
126   
127   memcpy(np.nh->switch_mac, &localmac, ETH_ALEN);
128   
129   initNgPacket(&np);
130   l=extractPacketAttributes(&np);
131   
132   initNgPacket(&np);
133   
134   
135   switch ( np.nh->code ) {
136    
137    case CODE_READ_REQ:
138     
139     for (ln=l->first; ln!=NULL; ln=ln->next) {
140      at=ln->data;
141      
142      switch ( at->attr ) {
143       
144       case ATTR_PRODUCT:
145        strcpy(np.ah->data, "NgEmu");
146        addPacketAttr(&np, ATTR_PRODUCT, strlen(np.ah->data), NULL);
147       break;
148       
149       case ATTR_UNK2:
150        addPacketShortAttr(&np, ATTR_UNK2, 0);
151       break;
152       
153       case ATTR_NAME:
154        strcpy(np.ah->data, "netgear switch emulator");
155        addPacketAttr(&np, ATTR_NAME, strlen(np.ah->data), NULL);
156       break;
157       
158       case ATTR_MAC:
159        memcpy(np.ah->data, &localmac, ETH_ALEN);
160        addPacketAttr(&np, ATTR_MAC, ETH_ALEN, NULL);
161       break;
162       
163       case ATTR_UNK5:
164        memset(np.ah->data, 0, 64);
165        addPacketAttr(&np, ATTR_UNK5, 64, NULL);
166       break;
167       
168       case ATTR_IP:
169        *(struct in_addr*)np.ah->data=localip;
170        addPacketAttr(&np, ATTR_IP, 4, NULL);
171       break;
172       
173       case ATTR_NETMASK:
174        *(in_addr_t*)np.ah->data=inet_addr("255.255.255.0");
175        addPacketAttr(&np, ATTR_NETMASK, 4, NULL);
176       break;
177       
178       case ATTR_GATEWAY:
179        *(in_addr_t*)np.ah->data=inet_addr("192.168.0.16");
180        addPacketAttr(&np, ATTR_GATEWAY, 4, NULL);
181       break;
182       
183       case ATTR_DHCP:
184        addPacketShortAttr(&np, ATTR_DHCP, 1);
185       break;
186       
187       case ATTR_UNK12:
188        addPacketByteAttr(&np, ATTR_UNK12, 1);
189       break;
190       
191       case ATTR_FIRM_VER:
192        strcpy(np.ah->data, "NgAdmin 0.0.1");
193        addPacketAttr(&np, ATTR_FIRM_VER, strlen(np.ah->data), NULL);
194       break;
195       
196       case ATTR_UNK15:
197        addPacketByteAttr(&np, ATTR_UNK15, 1);
198       break;
199       
200       case ATTR_PORTS_NUMBER:
201        addPacketByteAttr(&np, ATTR_PORTS_NUMBER, ports);
202       break;
203       
204       case ATTR_PORT_STATUS:
205        for (i=1; i<=ports; i++) {
206         np.ah->data[0]=i;
207         switch ( i&3 ) {
208          case 0: np.ah->data[2]=0; np.ah->data[1]=0; break;
209          case 1: np.ah->data[2]=1; np.ah->data[1]=SPEED_10; break;
210          case 2: np.ah->data[2]=1; np.ah->data[1]=SPEED_100; break;
211          case 3: np.ah->data[2]=1; np.ah->data[1]=SPEED_1000; 
212         }
213         addPacketAttr(&np, ATTR_PORT_STATUS, 3, NULL);
214        }
215       break;
216       
217       case ATTR_QOS_TYPE:
218        addPacketByteAttr(&np, ATTR_QOS_TYPE, QOS_PORT);
219       break;
220       
221       case ATTR_QOS_CONFIG:
222        for (i=1; i<=(int)ports; i++) {
223         np.ah->data[0]=i;
224         np.ah->data[1]=(i&3)+1;
225         addPacketAttr(&np, ATTR_QOS_CONFIG, 2, NULL);
226        }
227       break;
228       
229       case 0x5400:
230        addPacketByteAttr(&np, 0x5400, 0);
231       break;
232       
233       /*
234       case 0x1000: // System -> Monitoring -> Port Statistics
235        len=1+3*8;
236        for (i=1; i<=(int)ports; i++) {
237         memset(np.ah->data, 0, len);
238         addPacketAttr(&np, 0x1000, len, NULL);
239        }
240       break;
241       */
242       
243       case ATTR_MIRROR:
244        np.ah->data[0]=ports;
245        np.ah->data[1]=0;
246        len=(ports>>3)+((ports&7)!=0);
247        *(unsigned int*)&np.ah->data[2]=0;
248        for (i=0; i<ports-1; i+=2) {
249         np.ah->data[2+(i>>3)] |= 1<<(7-(i&7)) ;
250        }
251        addPacketAttr(&np, ATTR_MIRROR, 2+len, NULL);
252       break;
253       
254       case ATTR_VLAN_TYPE:
255        addPacketByteAttr(&np, ATTR_VLAN_TYPE, VLAN_DOT_ADV);
256       break;
257       
258       /*
259       case 0x7400:
260       break
261       */
262       
263       default:
264        addPacketEmptyAttr(&np, at->attr);
265       
266      }
267      
268     }
269     
270     np.nh->code=CODE_READ_REP;
271     len=getPacketTotalSize(&np);
272     
273    break;
274    
275    case CODE_WRITE_REQ:
276     np.nh->code=CODE_WRITE_REP;
277    break;
278    
279    default:
280     printf("unkown code\n");
281    
282   }
283   
284   
285   destroyList(l, (void(*)(void*))freeAttr);
286   
287   client.sin_addr.s_addr=htonl(INADDR_BROADCAST);
288   client.sin_port=htons(CLIENT_PORT);
289   if ( sendto(sock, buffer, len, 0, (struct sockaddr*)&client, sizeof(struct sockaddr))<0 ) {
290    perror("sendto");
291   }
292   
293   
294  }
295  
296  handler(0);
297  
298 }
299