]> git.ipfire.org Git - people/stevee/ipfire-2.x.git/blob - src/br2684ctl/br2684ctl.c
wsdd: Append --interface switches to the arguments array
[people/stevee/ipfire-2.x.git] / src / br2684ctl / br2684ctl.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <sys/ioctl.h>
6 #include <string.h>
7 #include <syslog.h>
8 #include <atm.h>
9 #include <linux/atmdev.h>
10 #include <linux/atmbr2684.h>
11
12 /* Written by Marcell GAL <cell@sch.bme.hu> to make use of the */
13 /* ioctls defined in the br2684... kernel patch */
14 /* Compile with cc -o br2684ctl br2684ctl.c -latm */
15
16 /*
17 Modified feb 2001 by Stephen Aaskov (saa@lasat.com)
18 - Added daemonization code
19 - Added syslog
20
21 TODO: Delete interfaces after exit?
22 */
23
24
25 #define LOG_NAME "RFC1483/2684 bridge"
26 #define LOG_OPTION LOG_PERROR
27 #define LOG_FACILITY LOG_LOCAL0
28
29
30 int lastsock, lastitf;
31
32
33 void fatal(const char *str, int i)
34 {
35 syslog (LOG_ERR,"Fatal: %s",str);
36 exit(-2);
37 };
38
39
40 void exitFunc(void)
41 {
42 syslog (LOG_PID,"Daemon terminated\n");
43 }
44
45
46 int create_pidfile(int num)
47 {
48 FILE *pidfile = NULL;
49 char name[32];
50
51 if (num < 0) return -1;
52
53 snprintf(name, 20, "/var/run/nas%d.pid", num);
54 pidfile = fopen(name, "w");
55 if (pidfile == NULL) return -1;
56 fprintf(pidfile, "%d", getpid());
57 fclose(pidfile);
58
59 return 0;
60 }
61
62 int create_br(char *nstr)
63 {
64 int num, err;
65
66 if(lastsock<0) {
67 lastsock = socket(PF_ATMPVC, SOCK_DGRAM, ATM_AAL5);
68 }
69 if (lastsock<0) {
70 syslog(LOG_ERR, "socket creation failed: %s",strerror(errno));
71 } else {
72 /* create the device with ioctl: */
73 num=atoi(nstr);
74 if( num>=0 && num<1234567890){
75 struct atm_newif_br2684 ni;
76 ni.backend_num = ATM_BACKEND_BR2684;
77 ni.media = BR2684_MEDIA_ETHERNET;
78 ni.mtu = 1500;
79 sprintf(ni.ifname, "nas%d", num);
80 err=ioctl (lastsock, ATM_NEWBACKENDIF, &ni);
81
82 if (err == 0)
83 syslog(LOG_INFO, "Interface \"%s\" created sucessfully\n",ni.ifname);
84 else
85 syslog(LOG_INFO, "Interface \"%s\" could not be created, reason: %s\n",
86 ni.ifname,
87 strerror(errno));
88 lastitf=num; /* even if we didn't create, because existed, assign_vcc wil want to know it! */
89 } else {
90 syslog(LOG_ERR,"err: strange interface number %d", num );
91 }
92 }
93 return 0;
94 }
95
96
97 int assign_vcc(char *astr, int encap, int bufsize, struct atm_qos qos)
98 {
99 int err;
100 struct sockaddr_atmpvc addr;
101 int fd;
102 struct atm_backend_br2684 be;
103
104 memset(&addr, 0, sizeof(addr));
105 err=text2atm(astr,(struct sockaddr *)(&addr), sizeof(addr), T2A_PVC);
106 if (err!=0)
107 syslog(LOG_ERR,"Could not parse ATM parameters (error=%d)\n",err);
108
109 #if 0
110 addr.sap_family = AF_ATMPVC;
111 addr.sap_addr.itf = itf;
112 addr.sap_addr.vpi = 0;
113 addr.sap_addr.vci = vci;
114 #endif
115 syslog(LOG_INFO,"Communicating over ATM %d.%d.%d, encapsulation: %s\n", addr.sap_addr.itf,
116 addr.sap_addr.vpi,
117 addr.sap_addr.vci,
118 encap?"VC mux":"LLC");
119
120 if ((fd = socket(PF_ATMPVC, SOCK_DGRAM, ATM_AAL5)) < 0)
121 syslog(LOG_ERR,"failed to create socket %d, reason: %s", errno,strerror(errno));
122
123 if (qos.aal == 0) {
124 qos.aal = ATM_AAL5;
125 qos.txtp.traffic_class = ATM_UBR;
126 qos.txtp.max_sdu = 1524;
127 qos.txtp.pcr = ATM_MAX_PCR;
128 qos.rxtp = qos.txtp;
129 }
130
131 if ( (err=setsockopt(fd,SOL_SOCKET,SO_SNDBUF, &bufsize ,sizeof(bufsize))) )
132 syslog(LOG_ERR,"setsockopt SO_SNDBUF: (%d) %s\n",err, strerror(err));
133
134 if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0)
135 syslog(LOG_ERR,"setsockopt SO_ATMQOS %d", errno);
136
137 err = connect(fd, (struct sockaddr*)&addr, sizeof(struct sockaddr_atmpvc));
138
139 if (err < 0)
140 fatal("failed to connect on socket", err);
141
142 /* attach the vcc to device: */
143
144 be.backend_num = ATM_BACKEND_BR2684;
145 be.ifspec.method = BR2684_FIND_BYIFNAME;
146 sprintf(be.ifspec.spec.ifname, "nas%d", lastitf);
147 be.fcs_in = BR2684_FCSIN_NO;
148 be.fcs_out = BR2684_FCSOUT_NO;
149 be.fcs_auto = 0;
150 be.encaps = encap ? BR2684_ENCAPS_VC : BR2684_ENCAPS_LLC;
151 be.has_vpiid = 0;
152 be.send_padding = 0;
153 be.min_size = 0;
154 err=ioctl (fd, ATM_SETBACKEND, &be);
155 if (err == 0)
156 syslog (LOG_INFO,"Interface configured");
157 else {
158 syslog (LOG_ERR,"Could not configure interface:%s",strerror(errno));
159 exit(2);
160 }
161 return fd ;
162 }
163
164
165 void usage(char *s)
166 {
167 printf("usage: %s [-b] [[-c number] [-e 0|1] [-s sndbuf] [-q qos] [-a [itf.]vpi.vci]*]*\n", s);
168 exit(1);
169 }
170
171
172
173 int main (int argc, char **argv)
174 {
175 int c, background=0, encap=0, sndbuf=8192;
176 struct atm_qos reqqos;
177 int itfnum;
178 lastsock=-1;
179 lastitf=0;
180
181 /* st qos to 0 */
182 memset(&reqqos, 0, sizeof(reqqos));
183
184 openlog (LOG_NAME,LOG_OPTION,LOG_FACILITY);
185 if (argc>1)
186 while ((c = getopt(argc, argv,"q:a:bc:e:s:?h")) !=EOF)
187 switch (c) {
188 case 'q':
189 printf ("optarg : %s",optarg);
190 if (text2qos(optarg,&reqqos,0)) fprintf(stderr,"QOS parameter invalid\n");
191 break;
192 case 'a':
193 assign_vcc(optarg, encap, sndbuf, reqqos);
194 break;
195 case 'b':
196 background=1;
197 break;
198 case 'c':
199 create_br(optarg);
200 itfnum = atoi(optarg);
201 break;
202 case 'e':
203 encap=(atoi(optarg));
204 if(encap<0){
205 syslog (LOG_ERR, "invalid encapsulation: %s:\n",optarg);
206 encap=0;
207 }
208 break;
209 case 's':
210 sndbuf=(atoi(optarg));
211 if(sndbuf<0){
212 syslog(LOG_ERR, "Invalid sndbuf: %s, using size of 8192 instead\n",optarg);
213 sndbuf=8192;
214 }
215 break;
216 case '?':
217 case 'h':
218 default:
219 usage(argv[0]);
220 }
221 else
222 usage(argv[0]);
223
224 if (argc != optind) usage(argv[0]);
225
226 if(lastsock>=0) close(lastsock);
227
228 if (background) {
229 pid_t pid;
230
231 pid=fork();
232 if (pid < 0) {
233 fprintf(stderr,"Error detaching\n");
234 exit(2);
235 } else if (pid)
236 exit(0); // This is the parent
237
238 // Become a process group and session group leader
239 if (setsid()<0) {
240 fprintf (stderr,"Could not set process group\n");
241 exit(2);
242 }
243
244 // Fork again to let process group leader exit
245 pid = fork();
246 if (pid < 0) {
247 fprintf(stderr,"Error detaching during second fork\n");
248 exit(2);
249 } else if (pid)
250 exit(0); // This is the parent
251
252 // Now we're ready for buisness
253 chdir("/"); // Don't keep directories in use
254 close(0); close(1); close(2); // Close stdin, -out and -error
255 /*
256 Note that this implementation does not keep an open
257 stdout/err.
258 If we need them they can be opened now
259 */
260
261 }
262
263 create_pidfile(itfnum);
264
265 syslog (LOG_INFO, "RFC 1483/2684 bridge daemon started\n");
266 atexit (exitFunc);
267
268 while (1) sleep(30); /* to keep the sockets... */
269 return 0;
270 }
271