www.usr.com/support/gpl/USR9107_release.1.4.tar.gz
[bcm963xx.git] / userapps / opensource / atm2684 / pvc2684ctl / pvc2684ctl.c
1 /* brpvc.c -- client for managing RFC2684 bridge-encapsulation VCs.
2
3    written by Chuck Musser <chuckie@well.com>
4 */
5
6 #include <stdio.h>             /* printf, read, write, etc.  */
7 #include <stdlib.h>            /* malloc, exit, etc.         */
8 #include <unistd.h>            /* getopt, atoi               */
9 #include <errno.h>             /* system errors              */
10 #include <sys/un.h>            /* unix domain sockets        */
11 #include <sys/types.h>         /* u_int32_t, etc.            */
12 #include <pwd.h>               /* getpwuid, etc.             */
13 // brcm
14 #include "atm.h"               /* general ATM stuff          */
15 #include "atmbr2684.h"         /* ATM bridging structs       */
16
17 #include "brpvc.h"
18
19 // brcm
20 #define OFFSET 100000
21
22 extern char *optarg;
23 extern int optind, opterr, optopt;
24
25 void clean_exit (char *str)
26 {
27   if(errno)
28      perror(str);
29   else
30     printf(str);
31   exit(-1);
32 }
33
34 int unix_connect(void)
35 {
36   int fd;
37   struct be_msg msg;
38   struct sockaddr_un addr;
39   
40   if( (fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
41     clean_exit("Can't create client socket");
42
43   bzero(&addr, sizeof(addr));
44   addr.sun_family = AF_LOCAL;
45   strncpy(addr.sun_path, BRPVC_SOCKPATH, sizeof(addr.sun_path) -1);
46
47   if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)))
48     clean_exit("Can't connect to server");
49   
50   bzero(&msg, sizeof(msg));
51   msg.msgtype = HELLO;
52   
53   if( send(fd, &msg, sizeof(msg), 0) < 0 )
54     clean_exit("Can't send HELLO message");
55
56   if( recv(fd, &msg, sizeof(msg), 0) <= 0 )
57     clean_exit("Can't receive receive OK response from server");
58   return fd;
59 }
60
61
62 void usage(int exitval)
63 {
64   printf("usage:  bctl -a -v <[intf].vpi.vci> -i <nas #> [-c count] [-g group name]\n");
65   printf("        bctl -d -v <[intf].vpi.vci> -i <nas #> [-c count] [-g group name]\n");
66   printf("        bctl -d -d group name\n");
67   printf("        bctl -l [-d group name]\n");
68   exit(exitval);
69 }
70
71
72
73 #ifdef BUILD_STATIC
74 int pvc2684ctl_main (int argc, char **argv)
75 #else
76 int main (int argc, char **argv)
77 #endif
78 {
79   int optchar, action = 0, count = 1, starting_nas_idx = -1, 
80     t2a_err, srv_fd, nbytes, header = 0;
81   char *endptr;
82   char name[MAX_GROUPNAME_LEN] = {};
83   struct be_msg smsg, rmsg;
84   struct be_memstat rstatmsg;
85   struct sockaddr_atmpvc vc;
86   struct passwd *pw;
87   // brcm
88   int encap=BR2684_ENCAPS_LLC, proto_filter=0, mode=0;
89   unsigned short vlan_id=-1;
90   
91   bzero(&vc, sizeof(vc));
92
93   while(1) {
94     optchar = getopt(argc, argv, "Madli:v:c:g:erft:");
95     if (optchar == -1)
96        break;
97
98     switch(optchar) {
99
100     case 'M': 
101     
102     srv_fd = unix_connect();
103     smsg.msgtype = MEM_STATS;
104
105     if( send(srv_fd, &smsg, sizeof(smsg), 0) < 0 )
106       clean_exit("Can't send MEM_STAT message");
107
108     nbytes = recv(srv_fd, &rstatmsg, sizeof(rstatmsg), 0);
109     if(nbytes == 0 )
110       clean_exit("connection closed waiting for MEM_STAT response\n");
111     else if(nbytes < 0)
112       clean_exit("Can't receive MEM_STAT response");
113     
114     printf("VC mallocs: %d\nVC frees: %d\nGroup mallocs: %d\nGroup frees:%d\n",
115            rstatmsg.vc_mallocs,rstatmsg.vc_frees,
116            rstatmsg.group_mallocs,rstatmsg.group_frees);
117     exit(0);
118     break;
119
120     case 'a':
121     case 'd':
122     case 'l':
123       action = optchar;
124       break;
125
126     case 'i':
127 // brcm
128 /*
129       starting_nas_idx = strtol(optarg, &endptr, 10);
130       if(*endptr || starting_nas_idx < 0) {
131         printf("Invalid interface index specified\n");
132         exit(1);
133       }
134 */
135       break;
136       
137     case 'v':
138       if((t2a_err = (text2atm(optarg, (struct sockaddr *)&vc, sizeof(vc), T2A_PVC)))) {
139         printf ("can't parse \"%s\".\n", optarg);
140         exit(1);
141       }
142 // brcm
143       {
144         int retval, num[3];
145         retval = sscanf(optarg, "%d.%d.%d", num, num+1, num+2);
146         starting_nas_idx = OFFSET*num[1]+num[2];
147       }
148       break;
149       
150     case 'c': 
151       count = strtol(optarg, &endptr, 10);
152       if(*endptr || count <= 0) {
153         printf("Invalid count specified\n");
154         exit(1);
155       }
156       break;
157
158 // brcm
159     case 'e':
160       encap=BR2684_ENCAPS_VC;
161       break;
162
163 // brcm
164     case 'f':
165       proto_filter = FILTER_PPPOE;
166       break;
167       
168 // brcm
169     case 'r':
170       mode=1;
171       break;
172 // brcm  add vlan id flag
173     case 't':
174       vlan_id = atoi(optarg);
175       break;
176
177     case 'g':
178       strncpy(name,optarg,MAX_GROUPNAME_LEN);
179
180     case '?':
181
182       break;
183
184     default:
185       printf ("getopt returned char %c\n", optchar);
186     }
187   }
188
189   int hasname = 31;
190   for(; hasname>0; hasname--) { 
191     if(name[hasname] != '\0') break;
192   }
193
194   switch(action) {
195
196   case 'a':
197   case 'd':
198
199     if(vc.sap_family == AF_ATMPVC) {
200
201       if(starting_nas_idx < 0) {
202
203         /* If you specify a PVC, you must specify an interface too  */
204         printf("No interface specified. Use the -i option.\n");
205         usage(1);
206       }
207
208     } else if(action == 'a') {
209
210       /* If this is an ADD, you need to specify the PVC.  */
211       printf("No VC specified. Use the -v option.\n");
212       usage(1);
213
214     } else if (!hasname) {
215
216       /* If it's not an ADD, it must be a DELETE. You need at least a name.  */
217       printf("No VC or VC group name specified. Use the -v or -g options.\n");
218       usage(1);
219
220     } else {
221
222       /* If we're here, no VC was specified, it's a DELETE and a group 
223          name was specified. Send a DELETE_GROUP message and exit.
224       */
225
226       bzero(&rmsg, sizeof(rmsg));
227       srv_fd = unix_connect();
228       smsg.msgtype = DELETE_GROUP;
229       strncpy(smsg.name,name,MAX_GROUPNAME_LEN);
230
231       if( send(srv_fd, &smsg, sizeof(smsg), 0) < 0 )
232         clean_exit("Can't send DELETE_GROUP message");
233
234       nbytes = recv(srv_fd, &rmsg, sizeof(rmsg), 0);
235       if(nbytes == 0 )
236         clean_exit("connection closed waiting for DELETE_GROUP response\n");
237       else if(nbytes < 0)
238       clean_exit("Can't receive response to DELETE_GROUP message");
239
240       if(rmsg.msgtype == GROUP_NOT_FOUND)
241         printf("group \"%s\" doesn't exist\n", name);
242
243         exit(0);
244     }
245
246     smsg.msgtype = (action == 'a' ? ADD : DELETE);
247     smsg.nas_idx = starting_nas_idx;
248     smsg.pvc     = vc;
249     strncpy(smsg.name,name,MAX_GROUPNAME_LEN);
250     // brcm
251     smsg.encap   = encap;
252     smsg.proto_filter   = proto_filter;
253     smsg.mode   = mode;
254     smsg.vlan_id = vlan_id;
255
256     bzero(&rmsg, sizeof(rmsg));
257     srv_fd = unix_connect();
258     
259     do {
260
261       if( send(srv_fd, &smsg, sizeof(smsg), 0) < 0 )
262         clean_exit("Can't send ADD or DELETE message");
263
264       nbytes = recv(srv_fd, &rmsg, sizeof(rmsg), 0);
265       if(nbytes == 0 )
266         clean_exit("connection closed waiting for ADD or DELETE response\n");
267       else if(nbytes < 0)
268       clean_exit("Can't receive response to ADD or DELETE message");
269         
270       switch(rmsg.msgtype) {
271
272       case VC_NOT_FOUND:
273
274         printf("No VC %d/%d on nas%d\n", 
275                smsg.pvc.sap_addr.vpi, 
276                smsg.pvc.sap_addr.vci, 
277                smsg.nas_idx);
278         break;
279         
280       case NOT_OWNER:
281
282         pw = getpwuid(rmsg.uid);
283         printf("Can't delete VC %d/%d on nas%d. owner is %s\n", 
284                smsg.pvc.sap_addr.vpi, 
285                smsg.pvc.sap_addr.vci, 
286                smsg.nas_idx,
287                pw->pw_name);
288         break;
289
290       case SOCK_FAILED: 
291
292         printf("Interface nas%d already in use\n", smsg.nas_idx);
293         break;
294
295       case INTERFACE_FAILED: 
296
297         printf("Interface nas%d couldn't be created\n", smsg.nas_idx);
298         break;
299
300       case NOMEM:
301
302         printf("Server can't allocate memory\n");
303         break;
304
305       case OK:
306         
307         break;
308         
309       default:
310
311         printf("Weird error: %d\n", rmsg.msgtype);
312       }
313       
314       smsg.nas_idx++; 
315       smsg.pvc.sap_addr.vci++;
316
317     } while(--count > 0);
318
319     break;
320
321   case 'l':
322
323     srv_fd = unix_connect();
324     smsg.msgtype = (strlen(name) ? LIST_GROUP : LIST_ALL );
325     strncpy(smsg.name,name,MAX_GROUPNAME_LEN);
326
327     if( send(srv_fd, &smsg, sizeof(smsg), 0) < 0 )
328       clean_exit("Can't send LIST_GROUP or LIST_ALL message");
329
330
331     do {
332
333       nbytes = recv(srv_fd, &rmsg, sizeof(rmsg), 0);
334       if(nbytes == 0 )
335         clean_exit("connection closed waiting for LIST_GROUP or LIST_ALL response\n");
336       else if(nbytes < 0)
337       clean_exit("Can't receive response to LIST_GROUP or LIST_ALL message");
338
339       if(rmsg.msgtype == GROUP_NOT_FOUND) {
340         if(strlen(name))
341           printf("Group %s not found\n", name);
342         else
343           printf("No VCs defined\n");
344         break;
345       } else if(!header) {
346 // brcm    
347         printf("\nVC          interface  mode             vlan_id\n");
348         printf("--          ---------  ------           ----------\n");
349 //      printf("\nVC          interface  group                            owner\n");
350 //      printf("--          ---------  ------                           -----\n");
351         header = 1;
352       }
353
354       if(rmsg.msgtype == OK) {
355         printf("%2d/%4d     nas%-6d  %-16s %d (X%02X)\n", 
356                rmsg.pvc.sap_addr.vpi,
357                rmsg.pvc.sap_addr.vci,
358                rmsg.nas_idx,
359                rmsg.mode? "Routing":    "Bridging",
360                rmsg.vlan_id, rmsg.vlan_id
361                 );
362       }
363     } while(rmsg.msgtype != LIST_END);
364
365     printf("\n");
366
367     break;
368
369   default:
370     printf("No command specified. Use -a, -d, or -l\n");
371   }
372   exit(0);
373 }