www.usr.com/support/gpl/USR9107_release.1.4.tar.gz
[bcm963xx.git] / userapps / opensource / ppp / pppoe / pppoatm.c
1 /* pppoatm.c - pppd plugin to implement PPPoATM protocol.
2  *
3  * Copyright 2000 Mitchell Blank Jr.
4  * Based in part on work from Jens Axboe and Paul Mackerras.
5  *
6  *  This program is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  as published by the Free Software Foundation; either version
9  *  2 of the License, or (at your option) any later version.
10  */
11 #include "pppd.h"
12 #include "pathnames.h"
13 #include "fsm.h" /* Needed for lcp.h to include cleanly */
14 #include "lcp.h"
15 #include <atm.h>
16 #include <linux/atmdev.h>
17 #include <linux/atmppp.h>
18 #include <sys/stat.h>
19 #include <net/if.h>
20 #include <sys/ioctl.h>
21
22 static struct sockaddr_atmpvc pvcaddr;
23 static char *qosstr = NULL;
24 static int pppoatm_accept = 0;
25 bool llc_encaps = 0;
26 bool vc_encaps = 0;
27 static int device_got_set = 0;
28 static int pppoatm_max_mtu, pppoatm_max_mru;
29
30 // brcm begin
31 struct channel pppoatm_channel;
32 static int fd_pppoa=0;
33
34 int setdevname_pppoatm(const char *cp);
35 //static int setdevname_pppoatm(const char *cp);
36 static void set_line_discipline_pppoatm(int fd);
37 // brcm end
38
39 static option_t my_options[] = {
40 #if 0
41         { "accept", o_bool, &pppoatm_accept,
42           "set PPPoATM socket to accept incoming connections", 1 },
43 #endif
44         { "llc-encaps", o_bool, &llc_encaps,
45           "use LLC encapsulation for PPPoATM", 1},
46         { "vc-encaps", o_bool, &vc_encaps,
47           "use VC multiplexing for PPPoATM (default)", 1},
48         { "qos", o_string, &qosstr,
49           "set QoS for PPPoATM connection", 1},
50         { NULL }
51 };
52
53 /* returns:
54  *  -1 if there's a problem with setting the device
55  *   0 if we can't parse "cp" as a valid name of a device
56  *   1 if "cp" is a reasonable thing to name a device
57  * Note that we don't actually open the device at this point
58  * We do need to fill in:
59  *   devnam: a string representation of the device
60  *   devstat: a stat structure of the device.  In this case
61  *     we're not opening a device, so we just make sure
62  *     to set up S_ISCHR(devstat.st_mode) != 1, so we
63  *     don't get confused that we're on stdin.
64  */
65 // brcm begin
66 int setdevname_pppoatm(const char *cp)
67 //static int setdevname_pppoatm(const char *cp)
68 // brcm end
69 {
70         struct sockaddr_atmpvc addr;
71 // brcm begin
72 //      extern struct stat devstat;
73 // brcm end
74         if (device_got_set)
75                 return 0;
76         info("PPPoATM setdevname_pppoatm");
77         memset(&addr, 0, sizeof addr);
78         if (text2atm(cp, (struct sockaddr *) &addr, sizeof(addr),
79             T2A_PVC | T2A_NAME) < 0)
80                 return 0;
81 // brcm begin
82 //      if (!dev_set_ok())
83 //              return -1;
84 // brcm end
85         memcpy(&pvcaddr, &addr, sizeof pvcaddr);
86         strlcpy(devnam, cp, sizeof devnam);
87 // brcm begin
88 //      devstat.st_mode = S_IFSOCK;
89 // brcm end
90         // brcm begin
91         the_channel = &pppoatm_channel;
92         //modem = 0;
93         lcp_wantoptions[0].neg_accompression = 0;
94         lcp_allowoptions[0].neg_accompression = 0;
95         lcp_wantoptions[0].neg_asyncmap = 0;
96         lcp_allowoptions[0].neg_asyncmap = 0;
97         lcp_wantoptions[0].neg_pcompression = 0;
98         // brcm end
99
100         info("PPPoATM setdevname_pppoatm - SUCCESS");
101         device_got_set = 1;
102         return 1;
103 }
104
105 static int setspeed_pppoatm(const char *cp)
106 {
107         return 0;
108 }
109
110 static int options_for_pppoatm(void)
111 {
112 // brcm begin
113 //      return options_from_devfile(_PATH_ATMOPT, devnam);
114 // brcm end
115 }
116
117 #define pppoatm_overhead() (llc_encaps ? 6 : 2)
118
119 // brcm2
120 static disconnect_pppoatm(int fd)
121 {
122         unsigned char ppp_disconn[64];
123         unsigned char * outp;
124
125         outp = ppp_disconn;
126         MAKEHEADER(outp, PPP_LCP);      // 2 bytes
127         PUTCHAR(5, outp);               // TERMREQ==5                   // 1 byte
128         PUTCHAR(2, outp);               // id=02                        // 1 byte
129     PUTSHORT(4, outp);          // HEADERLEN==4 in fsm.h        // 2 byte
130         
131         write(fd, ppp_disconn+2, 6);
132 }
133
134
135 static void no_device_given_pppoatm(void)
136 {
137         fatal("No vpi.vci specified");
138 }
139
140 static int open_device_pppoatm(void)
141 {
142         int fd;
143         struct atm_qos qos;
144         int i = 0;
145
146         if (!device_got_set)
147                 no_device_given_pppoatm();
148         fd = socket(AF_ATMPVC, SOCK_DGRAM, 0);
149         if (fd < 0)
150                 fatal("failed to create socket: %m");
151         // brcm
152         fd_pppoa = fd;
153         memset(&qos, 0, sizeof qos);
154         qos.txtp.traffic_class = qos.rxtp.traffic_class = ATM_UBR;
155         /* TODO: support simplified QoS setting */
156         if (qosstr != NULL)
157                 if (text2qos(qosstr, &qos, 0))
158                         fatal("Can't parse QoS: \"%s\"");
159         qos.txtp.max_sdu = lcp_allowoptions[0].mru + pppoatm_overhead();
160         qos.rxtp.max_sdu = lcp_wantoptions[0].mru + pppoatm_overhead();
161         qos.aal = ATM_AAL5;
162         if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0)
163                 fatal("setsockopt(SO_ATMQOS): %m");
164         /* TODO: accept on SVCs... */
165         if (connect(fd, (struct sockaddr *) &pvcaddr,
166             sizeof(struct sockaddr_atmpvc)))
167                 fatal("connect(%s): %m", devnam);
168         pppoatm_max_mtu = lcp_allowoptions[0].mru;
169         pppoatm_max_mru = lcp_wantoptions[0].mru;
170 // brcm begin
171         set_line_discipline_pppoatm(fd);
172 // brcm end
173
174         if (redisconn) {
175             while (i++ < 5) {
176                 usleep(300000);
177                 disconnect_pppoatm(fd);
178             }
179             usleep(100000);
180         }
181
182         return fd;
183 }
184
185 static void post_open_setup_pppoatm(int fd)
186 {
187         /* NOTHING */
188 }
189
190 static void pre_close_restore_pppoatm(int fd)
191 {
192         /* NOTHING */
193 }
194
195 // brcm begin
196 static void close_device_pppoatm(void)
197 {
198 //    close(fd);
199     if (fd_pppoa > 0)
200         close(fd_pppoa);
201 }
202 // brcm end
203
204 static void set_line_discipline_pppoatm(int fd)
205 {
206         struct atm_backend_ppp be;
207         be.backend_num = ATM_BACKEND_PPP;
208         if (!llc_encaps)
209                 be.encaps = PPPOATM_ENCAPS_VC;
210         else if (!vc_encaps)
211                 be.encaps = PPPOATM_ENCAPS_LLC;
212         else
213                 be.encaps = PPPOATM_ENCAPS_AUTODETECT;
214         if (ioctl(fd, ATM_SETBACKEND, &be) < 0)
215                 fatal("ioctl(ATM_SETBACKEND): %m");
216 }
217
218 static void reset_line_discipline_pppoatm(int fd)
219 {
220         atm_backend_t be = ATM_BACKEND_RAW;
221         /* 2.4 doesn't support this yet */
222         (void) ioctl(fd, ATM_SETBACKEND, &be);
223 }
224
225 // brcm begin
226 static void send_config_pppoatm(int mtu, u_int32_t asyncmap,
227         int pcomp, int accomp)
228 //static void send_config_pppoatm(int unit, int mtu, u_int32_t asyncmap,
229 //      int pcomp, int accomp)
230 // brcm end
231 {
232         int sock;
233         struct ifreq ifr;
234         if (mtu > pppoatm_max_mtu)
235                 error("Couldn't increase MTU to %d", mtu);
236         sock = socket(AF_INET, SOCK_DGRAM, 0);
237         if (sock < 0)
238                 fatal("Couldn't create IP socket: %m");
239         strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
240         ifr.ifr_mtu = mtu;
241         if (ioctl(sock, SIOCSIFMTU, (caddr_t) &ifr) < 0)
242                 fatal("ioctl(SIOCSIFMTU): %m");
243         (void) close (sock);
244 }
245
246 // brcm begin
247 static void recv_config_pppoatm(int mru, u_int32_t asyncmap,
248         int pcomp, int accomp)
249 //static void recv_config_pppoatm(int unit, int mru, u_int32_t asyncmap,
250 //      int pcomp, int accomp)
251 // brcm end
252 {
253         if (mru > pppoatm_max_mru)
254                 error("Couldn't increase MRU to %d", mru);
255 }
256
257 static void set_xaccm_pppoatm(int unit, ext_accm accm)
258 {
259         /* NOTHING */
260 }
261
262 // brcm begin
263 #if 0
264 void plugin_init(void)
265 {
266 #if _linux_
267         extern int new_style_driver;    /* From sys-linux.c */
268 #endif
269         static char *bad_options[] = {
270                 "noaccomp", "-ac",
271                 "default-asyncmap", "-am", "asyncmap", "-as", "escape",
272                 "receive-all",
273                 "crtscts", "-crtscts", "nocrtscts",
274                 "cdtrcts", "nocdtrcts",
275                 "xonxoff",
276                 "modem", "local", "sync",
277                 NULL };
278 #if _linux_
279         if (!new_style_driver)
280                 fatal("Kernel doesn't support ppp_generic - "
281                     "needed for PPPoATM");
282 #else
283         fatal("No PPPoATM support on this OS");
284 #endif
285         info("PPPoATM plugin_init");
286         add_options(my_options);
287         add_devname_class(setdevname_pppoatm);
288         setspeed_hook = setspeed_pppoatm;
289         options_for_device_hook = options_for_pppoatm;
290         open_device_hook = open_device_pppoatm;
291         post_open_setup_hook = post_open_setup_pppoatm;
292         pre_close_restore_hook = pre_close_restore_pppoatm;
293         no_device_given_hook = no_device_given_pppoatm;
294         set_line_discipline_hook = set_line_discipline_pppoatm;
295         reset_line_discipline_hook = reset_line_discipline_pppoatm;
296         send_config_hook = send_config_pppoatm;
297         recv_config_hook = recv_config_pppoatm;
298         set_xaccm_hook = set_xaccm_pppoatm;
299         {
300                 char **a;
301                 for (a = bad_options; *a != NULL; a++)
302                         remove_option(*a);
303         }
304         modem = 0;
305         lcp_wantoptions[0].neg_accompression = 0;
306         lcp_allowoptions[0].neg_accompression = 0;
307         lcp_wantoptions[0].neg_asyncmap = 0;
308         lcp_allowoptions[0].neg_asyncmap = 0;
309         lcp_wantoptions[0].neg_pcompression = 0;
310 }
311 #endif
312 // brcm end
313
314 // brcm begin
315 struct channel pppoatm_channel = {
316     options: NULL,
317     process_extra_options: NULL,
318     check_options: NULL,
319     connect: &open_device_pppoatm,
320     disconnect: &close_device_pppoatm,
321     establish_ppp: &generic_establish_ppp,
322     disestablish_ppp: &generic_disestablish_ppp,
323     send_config: &send_config_pppoatm,
324     recv_config: &recv_config_pppoatm,
325     close: NULL,
326     cleanup: NULL
327 };
328 // brcm end