|
1586
|
1 //========================================================================== |
|
|
2 // |
|
|
3 // src/sys-ecos.c |
|
|
4 // |
|
|
5 //========================================================================== |
|
|
6 //####ECOSGPLCOPYRIGHTBEGIN#### |
|
|
7 // ------------------------------------------- |
|
|
8 // This file is part of eCos, the Embedded Configurable Operating System. |
|
|
9 // Portions created by Nick Garnett are |
|
|
10 // Copyright (C) 2003, 2004 eCosCentric Ltd. |
|
|
11 // |
|
|
12 // eCos is free software; you can redistribute it and/or modify it under |
|
|
13 // the terms of the GNU General Public License as published by the Free |
|
|
14 // Software Foundation; either version 2 or (at your option) any later version. |
|
|
15 // |
|
|
16 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
|
|
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
|
18 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
|
19 // for more details. |
|
|
20 // |
|
|
21 // You should have received a copy of the GNU General Public License along |
|
|
22 // with eCos; if not, write to the Free Software Foundation, Inc., |
|
|
23 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|
|
24 // |
|
|
25 // As a special exception, if other files instantiate templates or use macros |
|
|
26 // or inline functions from this file, or you compile this file and link it |
|
|
27 // with other works to produce a work based on this file, this file does not |
|
|
28 // by itself cause the resulting work to be covered by the GNU General Public |
|
|
29 // License. However the source code for this file must still be made available |
|
|
30 // in accordance with section (3) of the GNU General Public License. |
|
|
31 // |
|
|
32 // This exception does not invalidate any other reasons why a work based on |
|
|
33 // this file might be covered by the GNU General Public License. |
|
|
34 // |
|
|
35 // ------------------------------------------- |
|
|
36 //####ECOSGPLCOPYRIGHTEND#### |
|
|
37 //####BSDCOPYRIGHTBEGIN#### |
|
|
38 // |
|
|
39 // ------------------------------------------- |
|
|
40 // |
|
|
41 // Portions of this software may have been derived from OpenBSD, |
|
|
42 // FreeBSD or other sources, and are covered by the appropriate |
|
|
43 // copyright disclaimers included herein. |
|
|
44 // |
|
|
45 // ------------------------------------------- |
|
|
46 // |
|
|
47 //####BSDCOPYRIGHTEND#### |
|
|
48 //========================================================================== |
|
|
49 |
|
|
50 /* |
|
|
51 * sys-bsd.c - System-dependent procedures for setting up |
|
|
52 * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.) |
|
|
53 * |
|
|
54 * Copyright (c) 1989 Carnegie Mellon University. |
|
|
55 * Copyright (c) 1995 The Australian National University. |
|
|
56 * All rights reserved. |
|
|
57 * |
|
|
58 * Redistribution and use in source and binary forms are permitted |
|
|
59 * provided that the above copyright notice and this paragraph are |
|
|
60 * duplicated in all such forms and that any documentation, |
|
|
61 * advertising materials, and other materials related to such |
|
|
62 * distribution and use acknowledge that the software was developed |
|
|
63 * by Carnegie Mellon University and The Australian National University. |
|
|
64 * The names of the Universities may not be used to endorse or promote |
|
|
65 * products derived from this software without specific prior written |
|
|
66 * permission. |
|
|
67 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
|
|
68 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
|
|
69 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
|
|
70 */ |
|
|
71 |
|
|
72 #ifndef lint |
|
|
73 //static char rcsid[] = "$FreeBSD: src/usr.sbin/pppd/sys-bsd.c,v 1.17 1999/08/28 01:19:08 peter Exp $"; |
|
|
74 #endif |
|
|
75 /* $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */ |
|
|
76 |
|
|
77 /* |
|
|
78 * TODO: |
|
|
79 */ |
|
|
80 |
|
|
81 //========================================================================== |
|
|
82 |
|
|
83 #include <pkgconf/system.h> |
|
|
84 #include <pkgconf/net.h> |
|
|
85 #include <pkgconf/ppp.h> |
|
|
86 |
|
|
87 #include <stdio.h> |
|
|
88 #include <string.h> |
|
|
89 #include <stdlib.h> |
|
|
90 #include <unistd.h> |
|
|
91 #include <errno.h> |
|
|
92 #include <fcntl.h> |
|
|
93 #include <termios.h> |
|
|
94 #include <signal.h> |
|
|
95 #define _KERNEL 1 |
|
|
96 #include <sys/param.h> |
|
|
97 #undef _KERNEL |
|
|
98 #include <sys/ioctl.h> |
|
|
99 #include <sys/types.h> |
|
|
100 #include <sys/socket.h> |
|
|
101 #include <sys/time.h> |
|
|
102 #include <sys/stat.h> |
|
|
103 #ifdef NetBSD1_2 |
|
|
104 #include <util.h> |
|
|
105 #endif |
|
|
106 #ifdef PPP_FILTER |
|
|
107 #include <net/bpf.h> |
|
|
108 #endif |
|
|
109 |
|
|
110 #include <cyg/ppp/syslog.h> |
|
|
111 |
|
|
112 #include <net/if.h> |
|
|
113 #include <cyg/ppp/net/ppp_defs.h> |
|
|
114 #include <cyg/ppp/net/if_ppp.h> |
|
|
115 #include <net/route.h> |
|
|
116 #include <net/if_dl.h> |
|
|
117 #include <netinet/in.h> |
|
|
118 |
|
|
119 #ifdef IPX_CHANGE |
|
|
120 #include <netipx/ipx.h> |
|
|
121 #endif |
|
|
122 |
|
|
123 #if RTM_VERSION >= 3 |
|
|
124 #include <sys/param.h> |
|
|
125 #if defined(NetBSD) && (NetBSD >= 199703) |
|
|
126 #include <netinet/if_inarp.h> |
|
|
127 #else /* NetBSD 1.2D or later */ |
|
|
128 #include <netinet/if_ether.h> |
|
|
129 #endif |
|
|
130 #endif |
|
|
131 |
|
|
132 #include "cyg/ppp/pppd.h" |
|
|
133 #include "cyg/ppp/fsm.h" |
|
|
134 #include "cyg/ppp/ipcp.h" |
|
|
135 |
|
|
136 #include "cyg/ppp/ppp_io.h" |
|
|
137 |
|
|
138 #include <cyg/ppp/ppp.h> |
|
|
139 |
|
|
140 //========================================================================== |
|
|
141 |
|
|
142 static int rtm_seq; |
|
|
143 |
|
|
144 static cyg_io_handle_t ppp_handle; /* IO subsystem handle to PPP stream */ |
|
|
145 struct tty ppp_tty; /* dummy TTY structure */ |
|
|
146 |
|
|
147 static cyg_handle_t ppp_rtc; |
|
|
148 static cyg_resolution_t ppp_rtc_resolution; |
|
|
149 |
|
|
150 static int loop_slave = -1; |
|
|
151 static int loop_master; |
|
|
152 |
|
|
153 static unsigned char inbuf[PPP_MTU + PPP_HDRLEN + 100]; /* buffer for chars read from input */ |
|
|
154 |
|
|
155 static int sockfd = -1; /* socket for doing interface ioctls */ |
|
|
156 |
|
|
157 static int if_is_up; /* the interface is currently up */ |
|
|
158 static u_int32_t ifaddrs[2]; /* local and remote addresses we set */ |
|
|
159 static u_int32_t default_route_gateway; /* gateway addr for default route */ |
|
|
160 static u_int32_t proxy_arp_addr; /* remote addr for proxy arp */ |
|
|
161 |
|
|
162 /* Prototypes for procedures local to this file. */ |
|
|
163 static int dodefaultroute __P((u_int32_t, int)); |
|
|
164 static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *)); |
|
|
165 |
|
|
166 static void wait_input_alarm(cyg_handle_t alarm, cyg_addrword_t data); |
|
|
167 #ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS |
|
|
168 void cyg_ppp_serial_callback( cyg_serial_line_status_t *s, |
|
|
169 CYG_ADDRWORD priv ); |
|
|
170 #endif |
|
|
171 |
|
|
172 u_int32_t netmask; /* IP netmask to set on interface */ |
|
|
173 |
|
|
174 //========================================================================== |
|
|
175 /* |
|
|
176 * sys_init - System-dependent initialization. |
|
|
177 */ |
|
|
178 void |
|
|
179 sys_init() |
|
|
180 { |
|
|
181 if( sockfd == -1 ) |
|
|
182 { |
|
|
183 /* Get an internet socket for doing socket ioctl's on. */ |
|
|
184 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
|
|
185 syslog(LOG_ERR, "Couldn't create IP socket: %d",errno); |
|
|
186 die(1); |
|
|
187 } |
|
|
188 } |
|
|
189 |
|
|
190 ppp_tty.pppd_wakeup = 0; |
|
|
191 ppp_tty.pppd_thread_running = true; |
|
|
192 |
|
|
193 ppp_rtc = cyg_real_time_clock(); |
|
|
194 ppp_rtc_resolution = cyg_clock_get_resolution( ppp_rtc ); |
|
|
195 |
|
|
196 cyg_alarm_create( ppp_rtc, |
|
|
197 wait_input_alarm, |
|
|
198 (cyg_addrword_t)&ppp_tty, |
|
|
199 &ppp_tty.alarm, |
|
|
200 &ppp_tty.alarm_obj); |
|
|
201 } |
|
|
202 |
|
|
203 //========================================================================== |
|
|
204 /* |
|
|
205 * sys_cleanup - restore any system state we modified before exiting: |
|
|
206 * mark the interface down, delete default route and/or proxy arp entry. |
|
|
207 * This should call die() because it's called from die(). |
|
|
208 */ |
|
|
209 void |
|
|
210 sys_cleanup() |
|
|
211 { |
|
|
212 struct ifreq ifr; |
|
|
213 |
|
|
214 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
215 if (if_is_up) { |
|
|
216 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
|
|
217 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0 |
|
|
218 && ((ifr.ifr_flags & IFF_UP) != 0)) { |
|
|
219 ifr.ifr_flags &= ~IFF_UP; |
|
|
220 ioctl(sockfd, SIOCSIFFLAGS, &ifr); |
|
|
221 } |
|
|
222 } |
|
|
223 if (ifaddrs[0] != 0) |
|
|
224 cifaddr(0, ifaddrs[0], ifaddrs[1]); |
|
|
225 if (default_route_gateway) |
|
|
226 cifdefaultroute(0, 0, default_route_gateway); |
|
|
227 if (proxy_arp_addr) |
|
|
228 cifproxyarp(0, proxy_arp_addr); |
|
|
229 |
|
|
230 if( sockfd != -1 ) |
|
|
231 { |
|
|
232 close(sockfd); |
|
|
233 sockfd = -1; |
|
|
234 } |
|
|
235 } |
|
|
236 |
|
|
237 //========================================================================== |
|
|
238 |
|
|
239 #ifdef __ECOS |
|
|
240 |
|
|
241 void |
|
|
242 sys_exit(void) |
|
|
243 { |
|
|
244 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
245 phase = PHASE_DEAD; |
|
|
246 while( ppp_tty.tx_thread_running ) |
|
|
247 { |
|
|
248 db_printf("kick tx thread\n"); |
|
|
249 cyg_semaphore_post( &ppp_tty.tx_sem ); |
|
|
250 cyg_thread_delay(100); |
|
|
251 } |
|
|
252 ppp_tty.pppd_thread_running = false; |
|
|
253 cyg_thread_exit(); |
|
|
254 } |
|
|
255 #endif |
|
|
256 |
|
|
257 //========================================================================== |
|
|
258 /* |
|
|
259 * sys_close - Clean up in a child process before execing. |
|
|
260 */ |
|
|
261 void |
|
|
262 sys_close() |
|
|
263 { |
|
|
264 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
265 if (loop_slave >= 0) { |
|
|
266 close(loop_slave); |
|
|
267 close(loop_master); |
|
|
268 } |
|
|
269 } |
|
|
270 |
|
|
271 //========================================================================== |
|
|
272 /* |
|
|
273 * sys_check_options - check the options that the user specified |
|
|
274 */ |
|
|
275 void |
|
|
276 sys_check_options() |
|
|
277 { |
|
|
278 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
279 } |
|
|
280 |
|
|
281 //========================================================================== |
|
|
282 /* |
|
|
283 * ppp_available - check whether the system has any ppp interfaces |
|
|
284 * (in fact we check whether we can do an ioctl on ppp0). |
|
|
285 */ |
|
|
286 int |
|
|
287 ppp_available() |
|
|
288 { |
|
|
289 int s, ok; |
|
|
290 struct ifreq ifr; |
|
|
291 extern char *no_ppp_msg; |
|
|
292 |
|
|
293 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) |
|
|
294 return 1; /* can't tell */ |
|
|
295 |
|
|
296 strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); |
|
|
297 ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; |
|
|
298 close(s); |
|
|
299 |
|
|
300 no_ppp_msg = "\ |
|
|
301 This system lacks kernel support for PPP. To include PPP support\n\ |
|
|
302 in the kernel, please follow the steps detailed in the README.bsd\n\ |
|
|
303 file in the ppp-2.2 distribution.\n"; |
|
|
304 return ok; |
|
|
305 } |
|
|
306 |
|
|
307 //========================================================================== |
|
|
308 /* |
|
|
309 * establish_ppp - Turn the serial port into a ppp interface. |
|
|
310 */ |
|
|
311 void |
|
|
312 establish_ppp(cyg_io_handle_t handle) |
|
|
313 { |
|
|
314 int s; |
|
|
315 int x; |
|
|
316 int err; |
|
|
317 |
|
|
318 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
319 |
|
|
320 ppp_handle = ppp_tty.t_handle = handle; |
|
|
321 ppp_tty.t_sc = NULL; |
|
|
322 |
|
|
323 s = splsoftnet(); |
|
|
324 |
|
|
325 err = cyg_ppp_pppopen( &ppp_tty ); |
|
|
326 |
|
|
327 if( err != 0 ) |
|
|
328 syslog( LOG_ERR, "Couldn't establish PPP interface: %d", err ); |
|
|
329 |
|
|
330 /* |
|
|
331 * Enable debug in the driver if requested. |
|
|
332 */ |
|
|
333 if (kdebugflag) { |
|
|
334 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) < 0) { |
|
|
335 syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %d",err); |
|
|
336 } else { |
|
|
337 x |= (kdebugflag & 0xFF) * SC_DEBUG; |
|
|
338 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) < 0) |
|
|
339 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %d",err); |
|
|
340 } |
|
|
341 } |
|
|
342 |
|
|
343 splx(s); |
|
|
344 } |
|
|
345 |
|
|
346 //========================================================================== |
|
|
347 /* |
|
|
348 * restore_loop - reattach the ppp unit to the loopback. |
|
|
349 */ |
|
|
350 void |
|
|
351 restore_loop() |
|
|
352 { |
|
|
353 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
354 } |
|
|
355 |
|
|
356 |
|
|
357 //========================================================================== |
|
|
358 /* |
|
|
359 * disestablish_ppp - Restore the serial port to normal operation. |
|
|
360 * This shouldn't call die() because it's called from die(). |
|
|
361 */ |
|
|
362 void |
|
|
363 disestablish_ppp(cyg_io_handle_t handle) |
|
|
364 { |
|
|
365 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
366 } |
|
|
367 |
|
|
368 //========================================================================== |
|
|
369 /* |
|
|
370 * Check whether the link seems not to be 8-bit clean. |
|
|
371 */ |
|
|
372 void |
|
|
373 clean_check() |
|
|
374 { |
|
|
375 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
376 } |
|
|
377 |
|
|
378 //========================================================================== |
|
|
379 /* |
|
|
380 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, |
|
|
381 * at the requested speed, etc. If `local' is true, set CLOCAL |
|
|
382 * regardless of whether the modem option was specified. |
|
|
383 * |
|
|
384 * For *BSD, we assume that speed_t values numerically equal bits/second. |
|
|
385 */ |
|
|
386 void |
|
|
387 set_up_tty(cyg_io_handle_t handle, int local) |
|
|
388 { |
|
|
389 cyg_serial_info_t cfg; |
|
|
390 int err; |
|
|
391 int len = sizeof(cfg); |
|
|
392 |
|
|
393 err = cyg_io_get_config( handle, |
|
|
394 CYG_IO_GET_CONFIG_SERIAL_INFO, |
|
|
395 &cfg, |
|
|
396 &len); |
|
|
397 |
|
|
398 if( err != 0 ) { |
|
|
399 syslog(LOG_ERR, "cyg_io_get_config: %d",err); |
|
|
400 die(1); |
|
|
401 } |
|
|
402 |
|
|
403 switch ( flowctl ) |
|
|
404 { |
|
|
405 case CYG_PPP_FLOWCTL_DEFAULT: |
|
|
406 break; |
|
|
407 |
|
|
408 case CYG_PPP_FLOWCTL_NONE: |
|
|
409 cfg.flags &= ~(CYGNUM_SERIAL_FLOW_RTSCTS_RX|CYGNUM_SERIAL_FLOW_RTSCTS_TX| |
|
|
410 CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_XONXOFF_TX); |
|
|
411 break; |
|
|
412 |
|
|
413 case CYG_PPP_FLOWCTL_HARDWARE: |
|
|
414 cfg.flags &= ~(CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_XONXOFF_TX); |
|
|
415 cfg.flags |= CYGNUM_SERIAL_FLOW_RTSCTS_RX|CYGNUM_SERIAL_FLOW_RTSCTS_TX; |
|
|
416 break; |
|
|
417 |
|
|
418 case CYG_PPP_FLOWCTL_SOFTWARE: |
|
|
419 cfg.flags &= ~(CYGNUM_SERIAL_FLOW_RTSCTS_RX|CYGNUM_SERIAL_FLOW_RTSCTS_TX); |
|
|
420 cfg.flags |= CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_XONXOFF_TX; |
|
|
421 break; |
|
|
422 } |
|
|
423 |
|
|
424 if( inspeed != 0 ) |
|
|
425 cfg.baud = inspeed; |
|
|
426 |
|
|
427 err = cyg_io_set_config( handle, |
|
|
428 CYG_IO_SET_CONFIG_SERIAL_INFO, |
|
|
429 &cfg, |
|
|
430 &len); |
|
|
431 |
|
|
432 if( err != 0 ) { |
|
|
433 syslog(LOG_ERR, "cyg_io_set_config: %d",err); |
|
|
434 die(1); |
|
|
435 } |
|
|
436 } |
|
|
437 |
|
|
438 //========================================================================== |
|
|
439 /* |
|
|
440 * restore_tty - restore the terminal to the saved settings. |
|
|
441 */ |
|
|
442 void |
|
|
443 restore_tty(cyg_io_handle_t handle) |
|
|
444 { |
|
|
445 #ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS |
|
|
446 if( modem ) |
|
|
447 { |
|
|
448 // Restore callback handler if it was set. |
|
|
449 |
|
|
450 Cyg_ErrNo err; |
|
|
451 cyg_uint32 len = sizeof(ppp_tty.serial_callbacks); |
|
|
452 |
|
|
453 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
454 |
|
|
455 err = cyg_io_set_config( handle, |
|
|
456 CYG_IO_SET_CONFIG_SERIAL_STATUS_CALLBACK, |
|
|
457 &ppp_tty.serial_callbacks, |
|
|
458 &len); |
|
|
459 |
|
|
460 if( err != 0 ) { |
|
|
461 syslog(LOG_ERR, "cyg_io_set_config(restore serial callbacks): %d",err); |
|
|
462 die(1); |
|
|
463 } |
|
|
464 } |
|
|
465 #endif |
|
|
466 } |
|
|
467 |
|
|
468 //========================================================================== |
|
|
469 /* |
|
|
470 * setdtr - control the DTR line on the serial port. |
|
|
471 * This is called from die(), so it shouldn't call die(). |
|
|
472 */ |
|
|
473 void |
|
|
474 setdtr(fd, on) |
|
|
475 int fd, on; |
|
|
476 { |
|
|
477 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
478 } |
|
|
479 |
|
|
480 //========================================================================== |
|
|
481 /* |
|
|
482 * output - Output PPP packet. |
|
|
483 */ |
|
|
484 void |
|
|
485 output(unit, p, len) |
|
|
486 int unit; |
|
|
487 u_char *p; |
|
|
488 int len; |
|
|
489 { |
|
|
490 Cyg_ErrNo err; |
|
|
491 struct uio uio; |
|
|
492 struct iovec iov; |
|
|
493 int s; |
|
|
494 |
|
|
495 if (debug) |
|
|
496 log_packet(p, len, "sent ", LOG_DEBUG); |
|
|
497 |
|
|
498 |
|
|
499 iov.iov_base = p; |
|
|
500 iov.iov_len = len; |
|
|
501 uio.uio_iov = &iov; |
|
|
502 uio.uio_iovcnt = 1; |
|
|
503 uio.uio_resid = len; |
|
|
504 uio.uio_segflg = UIO_USERSPACE; |
|
|
505 uio.uio_rw = UIO_WRITE; |
|
|
506 |
|
|
507 s = splsoftnet(); |
|
|
508 |
|
|
509 err = cyg_ppp_pppwrite( &ppp_tty, &uio, 0 ); |
|
|
510 |
|
|
511 splx(s); |
|
|
512 |
|
|
513 if( err != 0 ) |
|
|
514 syslog(LOG_ERR, "write: %d",err); |
|
|
515 |
|
|
516 } |
|
|
517 |
|
|
518 //========================================================================== |
|
|
519 |
|
|
520 #ifdef __ECOS |
|
|
521 |
|
|
522 static void wait_input_alarm(cyg_handle_t alarm, cyg_addrword_t data) |
|
|
523 { |
|
|
524 cyg_thread_release( ppp_tty.pppd_thread ); |
|
|
525 ppp_tty.pppd_wakeup = 1; |
|
|
526 } |
|
|
527 |
|
|
528 #ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS |
|
|
529 void cyg_ppp_serial_callback( cyg_serial_line_status_t *s, |
|
|
530 CYG_ADDRWORD priv ) |
|
|
531 { |
|
|
532 externC int kill_link; |
|
|
533 |
|
|
534 // db_printf("serial callback %d %x\n",s->which, s->value ); |
|
|
535 |
|
|
536 if( s->which == CYGNUM_SERIAL_STATUS_CARRIERDETECT ) |
|
|
537 { |
|
|
538 if( s->value == 0 ) |
|
|
539 { |
|
|
540 // CD lost |
|
|
541 kill_link = 1; |
|
|
542 cyg_thread_release( ppp_tty.pppd_thread ); |
|
|
543 ppp_tty.pppd_wakeup = 1; |
|
|
544 } |
|
|
545 else |
|
|
546 { |
|
|
547 // CD up |
|
|
548 ppp_tty.carrier_detected = 1; |
|
|
549 } |
|
|
550 } |
|
|
551 } |
|
|
552 #endif |
|
|
553 |
|
|
554 static void cyg_ppp_tx_thread(CYG_ADDRWORD arg) |
|
|
555 { |
|
|
556 ppp_tty.tx_thread_running = true; |
|
|
557 |
|
|
558 // Wait for the PPPD thread to get going and start the PPP |
|
|
559 // initialization phase. |
|
|
560 while(phase == PHASE_DEAD ) |
|
|
561 cyg_thread_delay(100); |
|
|
562 |
|
|
563 // Now loop until the link goes back down. |
|
|
564 while( phase != PHASE_DEAD ) |
|
|
565 { |
|
|
566 cyg_semaphore_wait( &ppp_tty.tx_sem ); |
|
|
567 |
|
|
568 if( phase == PHASE_DEAD ) |
|
|
569 break; |
|
|
570 |
|
|
571 // Call into PPP driver to get transmissions going. This is |
|
|
572 // only called if some other thread has failed to transmit all |
|
|
573 // of a packet due to a full buffer, or flow control. |
|
|
574 |
|
|
575 cyg_ppp_pppstart( &ppp_tty ); |
|
|
576 } |
|
|
577 |
|
|
578 db_printf("%s exiting\n", __PRETTY_FUNCTION__); |
|
|
579 ppp_tty.tx_thread_running = false; |
|
|
580 cyg_thread_exit(); |
|
|
581 } |
|
|
582 |
|
|
583 #endif |
|
|
584 |
|
|
585 |
|
|
586 //========================================================================== |
|
|
587 /* |
|
|
588 * wait_input - wait until there is data available on ttyfd, |
|
|
589 * for the length of time specified by *timo (indefinite |
|
|
590 * if timo is NULL). |
|
|
591 */ |
|
|
592 void |
|
|
593 wait_input(timo) |
|
|
594 struct timeval *timo; |
|
|
595 { |
|
|
596 if( timo != NULL ) |
|
|
597 { |
|
|
598 cyg_tick_count_t trigger = timo->tv_sec*ppp_rtc_resolution.divisor; |
|
|
599 |
|
|
600 // If the timeval has a microseconds value, just add another |
|
|
601 // second on to the trigger time. These are after all just |
|
|
602 // timeouts, not accurate timings, so a bit of imprecision |
|
|
603 // will not hurt. |
|
|
604 if( timo->tv_usec != 0 ) |
|
|
605 trigger += ppp_rtc_resolution.divisor; |
|
|
606 |
|
|
607 trigger += cyg_current_time(); |
|
|
608 |
|
|
609 // We set the alarm to retrigger after a second. This is in |
|
|
610 // case it catches cyg_io_read() at an uninterruptible |
|
|
611 // point. The alarm is disabled as soon as the read returns, |
|
|
612 // so the retrigger will usually not happen. |
|
|
613 cyg_alarm_initialize( ppp_tty.alarm, |
|
|
614 trigger, |
|
|
615 ppp_rtc_resolution.divisor ); |
|
|
616 } |
|
|
617 |
|
|
618 for(;;) |
|
|
619 { |
|
|
620 int s; |
|
|
621 int len = 1; |
|
|
622 Cyg_ErrNo err; |
|
|
623 cyg_serial_buf_info_t info; |
|
|
624 cyg_uint32 ilen = sizeof(info); |
|
|
625 |
|
|
626 #if 1 |
|
|
627 // Work out how many bytes are waiting in the serial device |
|
|
628 // buffer and read them all at once. If there are none, we |
|
|
629 // just wait for a single character to arrive. |
|
|
630 |
|
|
631 if( cyg_io_get_config( ppp_tty.t_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, |
|
|
632 &info, &ilen ) == 0 && info.rx_count > 1 ) |
|
|
633 { |
|
|
634 len = info.rx_count-1; |
|
|
635 if( len > sizeof(inbuf) ) |
|
|
636 len = sizeof(inbuf); |
|
|
637 } |
|
|
638 #endif |
|
|
639 |
|
|
640 if( timo != NULL ) |
|
|
641 cyg_alarm_enable( ppp_tty.alarm ); |
|
|
642 |
|
|
643 err = cyg_io_read( ppp_handle, &inbuf, &len ); |
|
|
644 |
|
|
645 if( timo != NULL ) |
|
|
646 cyg_alarm_disable( ppp_tty.alarm ); |
|
|
647 |
|
|
648 // db_printf("read: err %d len %d byte %02x\n",err,len,inbuf[0]); |
|
|
649 |
|
|
650 if( err == 0 ) |
|
|
651 { |
|
|
652 int i; |
|
|
653 |
|
|
654 // Pass all input data to PPP driver for analysis. If this |
|
|
655 // turns out to be for the PPPD, it will call |
|
|
656 // pppasyncctlp() which in turn will set |
|
|
657 // ppp_tty.pppd_wakeup. We detect that on return from |
|
|
658 // pppinput() and return to the caller to do pppd |
|
|
659 // processing. |
|
|
660 |
|
|
661 s = splsoftnet(); |
|
|
662 |
|
|
663 for( i = 0; i < len; i++ ) |
|
|
664 { |
|
|
665 err = cyg_ppp_pppinput( inbuf[i], &ppp_tty ); |
|
|
666 |
|
|
667 if( err != 0 ) |
|
|
668 syslog( LOG_ERR, "pppinput error: %d", err); |
|
|
669 |
|
|
670 } |
|
|
671 |
|
|
672 splx(s); |
|
|
673 |
|
|
674 } |
|
|
675 else if( err != -EINTR ) |
|
|
676 syslog( LOG_ERR, "Read error: %d",err); |
|
|
677 |
|
|
678 if( ppp_tty.pppd_wakeup ) |
|
|
679 { |
|
|
680 ppp_tty.pppd_wakeup = 0; |
|
|
681 break; |
|
|
682 } |
|
|
683 } |
|
|
684 } |
|
|
685 |
|
|
686 //========================================================================== |
|
|
687 /* |
|
|
688 * wait_time - wait for a given length of time or until a |
|
|
689 * signal is received. |
|
|
690 */ |
|
|
691 void |
|
|
692 wait_time(timo) |
|
|
693 struct timeval *timo; |
|
|
694 { |
|
|
695 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
696 } |
|
|
697 |
|
|
698 |
|
|
699 //========================================================================== |
|
|
700 /* |
|
|
701 * read_packet - get a PPP packet from the serial device. |
|
|
702 */ |
|
|
703 int |
|
|
704 read_packet(buf) |
|
|
705 u_char *buf; |
|
|
706 { |
|
|
707 int err; |
|
|
708 struct uio uio; |
|
|
709 struct iovec iov; |
|
|
710 int len = PPP_MTU + PPP_HDRLEN; |
|
|
711 int s; |
|
|
712 |
|
|
713 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
714 |
|
|
715 iov.iov_base = buf; |
|
|
716 iov.iov_len = len; |
|
|
717 uio.uio_iov = &iov; |
|
|
718 uio.uio_iovcnt = 1; |
|
|
719 uio.uio_resid = len; |
|
|
720 uio.uio_segflg = UIO_USERSPACE; |
|
|
721 uio.uio_rw = UIO_READ; |
|
|
722 |
|
|
723 s = splsoftnet(); |
|
|
724 |
|
|
725 err = cyg_ppp_pppread( &ppp_tty, &uio, 0 ); |
|
|
726 |
|
|
727 splx(s); |
|
|
728 |
|
|
729 if( err == EWOULDBLOCK ) |
|
|
730 return -1; |
|
|
731 |
|
|
732 if( err != 0 ) |
|
|
733 { |
|
|
734 syslog(LOG_ERR, "pppread: %d",err); |
|
|
735 die(1); |
|
|
736 } |
|
|
737 |
|
|
738 len -= uio.uio_resid; |
|
|
739 |
|
|
740 return len; |
|
|
741 } |
|
|
742 |
|
|
743 //========================================================================== |
|
|
744 /* |
|
|
745 * ppp_send_config - configure the transmit characteristics of |
|
|
746 * the ppp interface. |
|
|
747 */ |
|
|
748 void |
|
|
749 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) |
|
|
750 int unit, mtu; |
|
|
751 u_int32_t asyncmap; |
|
|
752 int pcomp, accomp; |
|
|
753 { |
|
|
754 u_int x; |
|
|
755 struct ifreq ifr; |
|
|
756 int err; |
|
|
757 int s; |
|
|
758 |
|
|
759 // db_printf("%s: unit %d mtu %d asyncmap %08x pcomp %08x accomp %08x\n", __PRETTY_FUNCTION__, |
|
|
760 // unit,mtu,asyncmap,pcomp,accomp); |
|
|
761 |
|
|
762 strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); |
|
|
763 ifr.ifr_mtu = mtu; |
|
|
764 if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) { |
|
|
765 syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %d",errno); |
|
|
766 quit(); |
|
|
767 } |
|
|
768 |
|
|
769 |
|
|
770 s = splsoftnet(); |
|
|
771 |
|
|
772 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSASYNCMAP, (caddr_t) &asyncmap, 0)) < 0) { |
|
|
773 syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %d",err); |
|
|
774 } |
|
|
775 |
|
|
776 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) < 0) { |
|
|
777 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err); |
|
|
778 } |
|
|
779 x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT; |
|
|
780 x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC; |
|
|
781 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) < 0) { |
|
|
782 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err); |
|
|
783 } |
|
|
784 |
|
|
785 splx(s); |
|
|
786 } |
|
|
787 |
|
|
788 |
|
|
789 //========================================================================== |
|
|
790 /* |
|
|
791 * ppp_set_xaccm - set the extended transmit ACCM for the interface. |
|
|
792 */ |
|
|
793 void |
|
|
794 ppp_set_xaccm(unit, accm) |
|
|
795 int unit; |
|
|
796 ext_accm accm; |
|
|
797 { |
|
|
798 int error; |
|
|
799 int s; |
|
|
800 |
|
|
801 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
802 |
|
|
803 s = splsoftnet(); |
|
|
804 |
|
|
805 error = cyg_ppp_ppptioctl( &ppp_tty, PPPIOCSXASYNCMAP, (caddr_t)accm, 0 ); |
|
|
806 |
|
|
807 splx(s); |
|
|
808 |
|
|
809 if( error != 0 ) |
|
|
810 syslog(LOG_WARNING, "ioctl(set extended ACCM): %d",error); |
|
|
811 } |
|
|
812 |
|
|
813 |
|
|
814 //========================================================================== |
|
|
815 /* |
|
|
816 * ppp_recv_config - configure the receive-side characteristics of |
|
|
817 * the ppp interface. |
|
|
818 */ |
|
|
819 void |
|
|
820 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) |
|
|
821 int unit, mru; |
|
|
822 u_int32_t asyncmap; |
|
|
823 int pcomp, accomp; |
|
|
824 { |
|
|
825 int x; |
|
|
826 int err; |
|
|
827 int s; |
|
|
828 |
|
|
829 s = splsoftnet(); |
|
|
830 |
|
|
831 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSMRU, (caddr_t) &mru, 0)) < 0) { |
|
|
832 syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %d",err); |
|
|
833 } |
|
|
834 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap, 0)) < 0) { |
|
|
835 syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %d",err); |
|
|
836 } |
|
|
837 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) < 0) { |
|
|
838 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err); |
|
|
839 } |
|
|
840 x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC; |
|
|
841 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) < 0) { |
|
|
842 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err); |
|
|
843 } |
|
|
844 |
|
|
845 splx(s); |
|
|
846 } |
|
|
847 |
|
|
848 //========================================================================== |
|
|
849 /* |
|
|
850 * ccp_test - ask kernel whether a given compression method |
|
|
851 * is acceptable for use. Returns 1 if the method and parameters |
|
|
852 * are OK, 0 if the method is known but the parameters are not OK |
|
|
853 * (e.g. code size should be reduced), or -1 if the method is unknown. |
|
|
854 */ |
|
|
855 int |
|
|
856 ccp_test(unit, opt_ptr, opt_len, for_transmit) |
|
|
857 int unit, opt_len, for_transmit; |
|
|
858 u_char *opt_ptr; |
|
|
859 { |
|
|
860 struct ppp_option_data data; |
|
|
861 int s; |
|
|
862 |
|
|
863 data.ptr = opt_ptr; |
|
|
864 data.length = opt_len; |
|
|
865 data.transmit = for_transmit; |
|
|
866 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
867 |
|
|
868 s = splsoftnet(); |
|
|
869 |
|
|
870 errno = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSCOMPRESS, (caddr_t) &data, 0 ); |
|
|
871 |
|
|
872 splx(s); |
|
|
873 |
|
|
874 if (errno == 0) |
|
|
875 return 1; |
|
|
876 else return (errno == ENOBUFS)? 0: -1; |
|
|
877 |
|
|
878 } |
|
|
879 |
|
|
880 //========================================================================== |
|
|
881 /* |
|
|
882 * ccp_flags_set - inform kernel about the current state of CCP. |
|
|
883 */ |
|
|
884 void |
|
|
885 ccp_flags_set(unit, isopen, isup) |
|
|
886 int unit, isopen, isup; |
|
|
887 { |
|
|
888 int x; |
|
|
889 |
|
|
890 int err; |
|
|
891 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
892 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) != 0) { |
|
|
893 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err); |
|
|
894 return; |
|
|
895 } |
|
|
896 x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN; |
|
|
897 x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP; |
|
|
898 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x,0)) != 0) |
|
|
899 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err); |
|
|
900 } |
|
|
901 |
|
|
902 //========================================================================== |
|
|
903 /* |
|
|
904 * ccp_fatal_error - returns 1 if decompression was disabled as a |
|
|
905 * result of an error detected after decompression of a packet, |
|
|
906 * 0 otherwise. This is necessary because of patent nonsense. |
|
|
907 */ |
|
|
908 int |
|
|
909 ccp_fatal_error(unit) |
|
|
910 int unit; |
|
|
911 { |
|
|
912 int x; |
|
|
913 int err; |
|
|
914 |
|
|
915 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
916 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) != 0) { |
|
|
917 syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %d",err); |
|
|
918 return 0; |
|
|
919 } |
|
|
920 return x & SC_DC_FERROR; |
|
|
921 } |
|
|
922 |
|
|
923 //========================================================================== |
|
|
924 /* |
|
|
925 * get_idle_time - return how long the link has been idle. |
|
|
926 */ |
|
|
927 int |
|
|
928 get_idle_time(u, ip) |
|
|
929 int u; |
|
|
930 struct ppp_idle *ip; |
|
|
931 { |
|
|
932 return cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGIDLE, (caddr_t)ip, 0) == 0; |
|
|
933 } |
|
|
934 |
|
|
935 |
|
|
936 //========================================================================== |
|
|
937 |
|
|
938 #ifdef PPP_FILTER |
|
|
939 /* |
|
|
940 * set_filters - transfer the pass and active filters to the kernel. |
|
|
941 */ |
|
|
942 int |
|
|
943 set_filters(pass, active) |
|
|
944 struct bpf_program *pass, *active; |
|
|
945 { |
|
|
946 int ret = 1; |
|
|
947 |
|
|
948 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
949 if (pass->bf_len > 0) { |
|
|
950 if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) { |
|
|
951 syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m"); |
|
|
952 ret = 0; |
|
|
953 } |
|
|
954 } |
|
|
955 if (active->bf_len > 0) { |
|
|
956 if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) { |
|
|
957 syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m"); |
|
|
958 ret = 0; |
|
|
959 } |
|
|
960 } |
|
|
961 return ret; |
|
|
962 } |
|
|
963 #endif |
|
|
964 |
|
|
965 //========================================================================== |
|
|
966 /* |
|
|
967 * sifvjcomp - config tcp header compression |
|
|
968 */ |
|
|
969 int |
|
|
970 sifvjcomp(u, vjcomp, cidcomp, maxcid) |
|
|
971 int u, vjcomp, cidcomp, maxcid; |
|
|
972 { |
|
|
973 u_int x; |
|
|
974 int err; |
|
|
975 |
|
|
976 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) != 0) { |
|
|
977 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err); |
|
|
978 return 0; |
|
|
979 } |
|
|
980 x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP; |
|
|
981 x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID; |
|
|
982 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) != 0) { |
|
|
983 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err); |
|
|
984 return 0; |
|
|
985 } |
|
|
986 if (vjcomp && ((err=cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSMAXCID, (caddr_t) &maxcid, 0)) != 0)) { |
|
|
987 syslog(LOG_ERR, "ioctl(PPPIOCSMAXCID): %d",err); |
|
|
988 return 0; |
|
|
989 } |
|
|
990 return 1; |
|
|
991 } |
|
|
992 |
|
|
993 //========================================================================== |
|
|
994 /* |
|
|
995 * sifup - Config the interface up and enable IP packets to pass. |
|
|
996 */ |
|
|
997 int |
|
|
998 sifup(u) |
|
|
999 int u; |
|
|
1000 { |
|
|
1001 struct ifreq ifr; |
|
|
1002 |
|
|
1003 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1004 strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); |
|
|
1005 if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { |
|
|
1006 syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); |
|
|
1007 return 0; |
|
|
1008 } |
|
|
1009 ifr.ifr_flags |= IFF_UP; |
|
|
1010 if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { |
|
|
1011 syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); |
|
|
1012 return 0; |
|
|
1013 } |
|
|
1014 if_is_up = 1; |
|
|
1015 return 1; |
|
|
1016 } |
|
|
1017 |
|
|
1018 //========================================================================== |
|
|
1019 /* |
|
|
1020 * sifnpmode - Set the mode for handling packets for a given NP. |
|
|
1021 */ |
|
|
1022 int |
|
|
1023 sifnpmode(u, proto, mode) |
|
|
1024 int u; |
|
|
1025 int proto; |
|
|
1026 enum NPmode mode; |
|
|
1027 { |
|
|
1028 struct npioctl npi; |
|
|
1029 |
|
|
1030 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1031 npi.protocol = proto; |
|
|
1032 npi.mode = mode; |
|
|
1033 { |
|
|
1034 int err; |
|
|
1035 |
|
|
1036 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSNPMODE, (caddr_t)&npi, 0)) < 0) { |
|
|
1037 syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %d", proto, mode,err); |
|
|
1038 return 0; |
|
|
1039 } |
|
|
1040 } |
|
|
1041 |
|
|
1042 return 1; |
|
|
1043 } |
|
|
1044 |
|
|
1045 //========================================================================== |
|
|
1046 /* |
|
|
1047 * sifdown - Config the interface down and disable IP. |
|
|
1048 */ |
|
|
1049 int |
|
|
1050 sifdown(u) |
|
|
1051 int u; |
|
|
1052 { |
|
|
1053 struct ifreq ifr; |
|
|
1054 int rv; |
|
|
1055 struct npioctl npi; |
|
|
1056 |
|
|
1057 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1058 rv = 1; |
|
|
1059 npi.protocol = PPP_IP; |
|
|
1060 npi.mode = NPMODE_ERROR; |
|
|
1061 { |
|
|
1062 int err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSNPMODE, (caddr_t) &npi, 0); |
|
|
1063 if( err < 0 ) |
|
|
1064 syslog(LOG_WARNING, "ioctl(PPPIOCSNPMODE): %d",err); |
|
|
1065 } |
|
|
1066 strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); |
|
|
1067 if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { |
|
|
1068 syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); |
|
|
1069 rv = 0; |
|
|
1070 } else { |
|
|
1071 ifr.ifr_flags &= ~IFF_UP; |
|
|
1072 if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { |
|
|
1073 syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); |
|
|
1074 rv = 0; |
|
|
1075 } else |
|
|
1076 if_is_up = 0; |
|
|
1077 } |
|
|
1078 return rv; |
|
|
1079 return 0; |
|
|
1080 } |
|
|
1081 |
|
|
1082 //========================================================================== |
|
|
1083 /* |
|
|
1084 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr, |
|
|
1085 * if it exists. |
|
|
1086 */ |
|
|
1087 #define SET_SA_FAMILY(addr, family) \ |
|
|
1088 BZERO((char *) &(addr), sizeof(addr)); \ |
|
|
1089 addr.sa_family = (family); \ |
|
|
1090 addr.sa_len = sizeof(addr); |
|
|
1091 |
|
|
1092 //========================================================================== |
|
|
1093 /* |
|
|
1094 * sifaddr - Config the interface IP addresses and netmask. |
|
|
1095 */ |
|
|
1096 int |
|
|
1097 sifaddr(u, o, h, m) |
|
|
1098 int u; |
|
|
1099 u_int32_t o, h, m; |
|
|
1100 { |
|
|
1101 struct ifaliasreq ifra; |
|
|
1102 struct ifreq ifr; |
|
|
1103 |
|
|
1104 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1105 strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); |
|
|
1106 SET_SA_FAMILY(ifra.ifra_addr, AF_INET); |
|
|
1107 ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; |
|
|
1108 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); |
|
|
1109 ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; |
|
|
1110 if (m != 0) { |
|
|
1111 SET_SA_FAMILY(ifra.ifra_mask, AF_INET); |
|
|
1112 ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m; |
|
|
1113 } else |
|
|
1114 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); |
|
|
1115 BZERO(&ifr, sizeof(ifr)); |
|
|
1116 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); |
|
|
1117 if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) { |
|
|
1118 if (errno != EADDRNOTAVAIL) |
|
|
1119 syslog(LOG_WARNING, "Couldn't remove interface address: %d",errno); |
|
|
1120 } |
|
|
1121 if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) { |
|
|
1122 if (errno != EEXIST) { |
|
|
1123 syslog(LOG_ERR, "Couldn't set interface address: %d",errno); |
|
|
1124 return 0; |
|
|
1125 } |
|
|
1126 syslog(LOG_WARNING, |
|
|
1127 "Couldn't set interface address: Address %s already exists", |
|
|
1128 ip_ntoa(o)); |
|
|
1129 } |
|
|
1130 ifaddrs[0] = o; |
|
|
1131 ifaddrs[1] = h; |
|
|
1132 return 1; |
|
|
1133 } |
|
|
1134 |
|
|
1135 //========================================================================== |
|
|
1136 /* |
|
|
1137 * cifaddr - Clear the interface IP addresses, and delete routes |
|
|
1138 * through the interface if possible. |
|
|
1139 */ |
|
|
1140 int |
|
|
1141 cifaddr(u, o, h) |
|
|
1142 int u; |
|
|
1143 u_int32_t o, h; |
|
|
1144 { |
|
|
1145 struct ifaliasreq ifra; |
|
|
1146 |
|
|
1147 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1148 ifaddrs[0] = 0; |
|
|
1149 strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); |
|
|
1150 SET_SA_FAMILY(ifra.ifra_addr, AF_INET); |
|
|
1151 ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o; |
|
|
1152 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); |
|
|
1153 ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; |
|
|
1154 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); |
|
|
1155 if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) { |
|
|
1156 if (errno != EADDRNOTAVAIL) |
|
|
1157 syslog(LOG_WARNING, "Couldn't delete interface address: %m"); |
|
|
1158 return 0; |
|
|
1159 } |
|
|
1160 return 1; |
|
|
1161 } |
|
|
1162 |
|
|
1163 //========================================================================== |
|
|
1164 /* |
|
|
1165 * sifdefaultroute - assign a default route through the address given. |
|
|
1166 */ |
|
|
1167 int |
|
|
1168 sifdefaultroute(u, l, g) |
|
|
1169 int u; |
|
|
1170 u_int32_t l, g; |
|
|
1171 { |
|
|
1172 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1173 return dodefaultroute(g, 's'); |
|
|
1174 } |
|
|
1175 |
|
|
1176 //========================================================================== |
|
|
1177 /* |
|
|
1178 * cifdefaultroute - delete a default route through the address given. |
|
|
1179 */ |
|
|
1180 int |
|
|
1181 cifdefaultroute(u, l, g) |
|
|
1182 int u; |
|
|
1183 u_int32_t l, g; |
|
|
1184 { |
|
|
1185 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1186 return dodefaultroute(g, 'c'); |
|
|
1187 } |
|
|
1188 |
|
|
1189 //========================================================================== |
|
|
1190 /* |
|
|
1191 * dodefaultroute - talk to a routing socket to add/delete a default route. |
|
|
1192 */ |
|
|
1193 static int |
|
|
1194 dodefaultroute(g, cmd) |
|
|
1195 u_int32_t g; |
|
|
1196 int cmd; |
|
|
1197 { |
|
|
1198 int routes; |
|
|
1199 struct { |
|
|
1200 struct rt_msghdr hdr; |
|
|
1201 struct sockaddr_in dst; |
|
|
1202 struct sockaddr_in gway; |
|
|
1203 struct sockaddr_in mask; |
|
|
1204 } rtmsg; |
|
|
1205 |
|
|
1206 db_printf("%s %08x %c\n", __PRETTY_FUNCTION__,g,cmd); |
|
|
1207 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { |
|
|
1208 syslog(LOG_ERR, "Couldn't %s default route: socket: %d", |
|
|
1209 cmd=='s'? "add": "delete",errno); |
|
|
1210 return 0; |
|
|
1211 } |
|
|
1212 |
|
|
1213 memset(&rtmsg, 0, sizeof(rtmsg)); |
|
|
1214 rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE; |
|
|
1215 rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; |
|
|
1216 rtmsg.hdr.rtm_version = RTM_VERSION; |
|
|
1217 rtmsg.hdr.rtm_seq = ++rtm_seq; |
|
|
1218 rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; |
|
|
1219 rtmsg.dst.sin_len = sizeof(rtmsg.dst); |
|
|
1220 rtmsg.dst.sin_family = AF_INET; |
|
|
1221 rtmsg.gway.sin_len = sizeof(rtmsg.gway); |
|
|
1222 rtmsg.gway.sin_family = AF_INET; |
|
|
1223 rtmsg.gway.sin_addr.s_addr = g; |
|
|
1224 rtmsg.mask.sin_len = sizeof(rtmsg.dst); |
|
|
1225 rtmsg.mask.sin_family = AF_INET; |
|
|
1226 |
|
|
1227 rtmsg.hdr.rtm_msglen = sizeof(rtmsg); |
|
|
1228 if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) { |
|
|
1229 syslog(LOG_ERR, "Couldn't %s default route: %d", |
|
|
1230 cmd=='s'? "add": "delete",errno); |
|
|
1231 close(routes); |
|
|
1232 return 0; |
|
|
1233 } |
|
|
1234 |
|
|
1235 close(routes); |
|
|
1236 default_route_gateway = (cmd == 's')? g: 0; |
|
|
1237 return 1; |
|
|
1238 } |
|
|
1239 |
|
|
1240 //========================================================================== |
|
|
1241 |
|
|
1242 #if RTM_VERSION >= 3 |
|
|
1243 |
|
|
1244 /* |
|
|
1245 * sifproxyarp - Make a proxy ARP entry for the peer. |
|
|
1246 */ |
|
|
1247 static struct { |
|
|
1248 struct rt_msghdr hdr; |
|
|
1249 struct sockaddr_inarp dst; |
|
|
1250 struct sockaddr_dl hwa; |
|
|
1251 char extra[128]; |
|
|
1252 } arpmsg; |
|
|
1253 |
|
|
1254 static int arpmsg_valid; |
|
|
1255 |
|
|
1256 int |
|
|
1257 sifproxyarp(unit, hisaddr) |
|
|
1258 int unit; |
|
|
1259 u_int32_t hisaddr; |
|
|
1260 { |
|
|
1261 int routes; |
|
|
1262 |
|
|
1263 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1264 /* |
|
|
1265 * Get the hardware address of an interface on the same subnet |
|
|
1266 * as our local address. |
|
|
1267 */ |
|
|
1268 memset(&arpmsg, 0, sizeof(arpmsg)); |
|
|
1269 if (!get_ether_addr(hisaddr, &arpmsg.hwa)) { |
|
|
1270 syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP"); |
|
|
1271 return 0; |
|
|
1272 } |
|
|
1273 |
|
|
1274 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { |
|
|
1275 syslog(LOG_ERR, "Couldn't add proxy arp entry: socket: %m"); |
|
|
1276 return 0; |
|
|
1277 } |
|
|
1278 |
|
|
1279 arpmsg.hdr.rtm_type = RTM_ADD; |
|
|
1280 arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC; |
|
|
1281 arpmsg.hdr.rtm_version = RTM_VERSION; |
|
|
1282 arpmsg.hdr.rtm_seq = ++rtm_seq; |
|
|
1283 arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; |
|
|
1284 arpmsg.hdr.rtm_inits = RTV_EXPIRE; |
|
|
1285 arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp); |
|
|
1286 arpmsg.dst.sin_family = AF_INET; |
|
|
1287 arpmsg.dst.sin_addr.s_addr = hisaddr; |
|
|
1288 arpmsg.dst.sin_other = SIN_PROXY; |
|
|
1289 |
|
|
1290 arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg |
|
|
1291 + arpmsg.hwa.sdl_len; |
|
|
1292 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { |
|
|
1293 syslog(LOG_ERR, "Couldn't add proxy arp entry: %m"); |
|
|
1294 close(routes); |
|
|
1295 return 0; |
|
|
1296 } |
|
|
1297 |
|
|
1298 close(routes); |
|
|
1299 arpmsg_valid = 1; |
|
|
1300 proxy_arp_addr = hisaddr; |
|
|
1301 return 1; |
|
|
1302 } |
|
|
1303 |
|
|
1304 /* |
|
|
1305 * cifproxyarp - Delete the proxy ARP entry for the peer. |
|
|
1306 */ |
|
|
1307 int |
|
|
1308 cifproxyarp(unit, hisaddr) |
|
|
1309 int unit; |
|
|
1310 u_int32_t hisaddr; |
|
|
1311 { |
|
|
1312 int routes; |
|
|
1313 |
|
|
1314 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1315 if (!arpmsg_valid) |
|
|
1316 return 0; |
|
|
1317 arpmsg_valid = 0; |
|
|
1318 |
|
|
1319 arpmsg.hdr.rtm_type = RTM_DELETE; |
|
|
1320 arpmsg.hdr.rtm_seq = ++rtm_seq; |
|
|
1321 |
|
|
1322 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) { |
|
|
1323 syslog(LOG_ERR, "Couldn't delete proxy arp entry: socket: %m"); |
|
|
1324 return 0; |
|
|
1325 } |
|
|
1326 |
|
|
1327 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) { |
|
|
1328 syslog(LOG_ERR, "Couldn't delete proxy arp entry: %m"); |
|
|
1329 close(routes); |
|
|
1330 return 0; |
|
|
1331 } |
|
|
1332 |
|
|
1333 close(routes); |
|
|
1334 proxy_arp_addr = 0; |
|
|
1335 return 1; |
|
|
1336 } |
|
|
1337 |
|
|
1338 //========================================================================== |
|
|
1339 |
|
|
1340 #else /* RTM_VERSION */ |
|
|
1341 |
|
|
1342 /* |
|
|
1343 * sifproxyarp - Make a proxy ARP entry for the peer. |
|
|
1344 */ |
|
|
1345 int |
|
|
1346 sifproxyarp(unit, hisaddr) |
|
|
1347 int unit; |
|
|
1348 u_int32_t hisaddr; |
|
|
1349 { |
|
|
1350 struct arpreq arpreq; |
|
|
1351 struct { |
|
|
1352 struct sockaddr_dl sdl; |
|
|
1353 char space[128]; |
|
|
1354 } dls; |
|
|
1355 |
|
|
1356 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1357 BZERO(&arpreq, sizeof(arpreq)); |
|
|
1358 |
|
|
1359 /* |
|
|
1360 * Get the hardware address of an interface on the same subnet |
|
|
1361 * as our local address. |
|
|
1362 */ |
|
|
1363 if (!get_ether_addr(hisaddr, &dls.sdl)) { |
|
|
1364 syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP"); |
|
|
1365 return 0; |
|
|
1366 } |
|
|
1367 |
|
|
1368 arpreq.arp_ha.sa_len = sizeof(struct sockaddr); |
|
|
1369 arpreq.arp_ha.sa_family = AF_UNSPEC; |
|
|
1370 BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen); |
|
|
1371 SET_SA_FAMILY(arpreq.arp_pa, AF_INET); |
|
|
1372 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; |
|
|
1373 arpreq.arp_flags = ATF_PERM | ATF_PUBL; |
|
|
1374 if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) { |
|
|
1375 syslog(LOG_ERR, "Couldn't add proxy arp entry: %m"); |
|
|
1376 return 0; |
|
|
1377 } |
|
|
1378 |
|
|
1379 proxy_arp_addr = hisaddr; |
|
|
1380 return 1; |
|
|
1381 } |
|
|
1382 |
|
|
1383 /* |
|
|
1384 * cifproxyarp - Delete the proxy ARP entry for the peer. |
|
|
1385 */ |
|
|
1386 int |
|
|
1387 cifproxyarp(unit, hisaddr) |
|
|
1388 int unit; |
|
|
1389 u_int32_t hisaddr; |
|
|
1390 { |
|
|
1391 struct arpreq arpreq; |
|
|
1392 |
|
|
1393 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1394 BZERO(&arpreq, sizeof(arpreq)); |
|
|
1395 SET_SA_FAMILY(arpreq.arp_pa, AF_INET); |
|
|
1396 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; |
|
|
1397 if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) { |
|
|
1398 syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m"); |
|
|
1399 return 0; |
|
|
1400 } |
|
|
1401 proxy_arp_addr = 0; |
|
|
1402 return 1; |
|
|
1403 } |
|
|
1404 #endif /* RTM_VERSION */ |
|
|
1405 |
|
|
1406 |
|
|
1407 //========================================================================== |
|
|
1408 /* |
|
|
1409 * get_ether_addr - get the hardware address of an interface on the |
|
|
1410 * the same subnet as ipaddr. |
|
|
1411 */ |
|
|
1412 #define MAX_IFS 32 |
|
|
1413 |
|
|
1414 static int |
|
|
1415 get_ether_addr(ipaddr, hwaddr) |
|
|
1416 u_int32_t ipaddr; |
|
|
1417 struct sockaddr_dl *hwaddr; |
|
|
1418 { |
|
|
1419 struct ifreq *ifr, *ifend, *ifp; |
|
|
1420 u_int32_t ina, mask; |
|
|
1421 struct sockaddr_dl *dla; |
|
|
1422 struct ifreq ifreq; |
|
|
1423 struct ifconf ifc; |
|
|
1424 struct ifreq ifs[MAX_IFS]; |
|
|
1425 |
|
|
1426 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1427 ifc.ifc_len = sizeof(ifs); |
|
|
1428 ifc.ifc_req = ifs; |
|
|
1429 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { |
|
|
1430 syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m"); |
|
|
1431 return 0; |
|
|
1432 } |
|
|
1433 |
|
|
1434 /* |
|
|
1435 * Scan through looking for an interface with an Internet |
|
|
1436 * address on the same subnet as `ipaddr'. |
|
|
1437 */ |
|
|
1438 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); |
|
|
1439 for (ifr = ifc.ifc_req; ifr < ifend; |
|
|
1440 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr |
|
|
1441 + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) { |
|
|
1442 if (ifr->ifr_addr.sa_family == AF_INET) { |
|
|
1443 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; |
|
|
1444 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); |
|
|
1445 /* |
|
|
1446 * Check that the interface is up, and not point-to-point |
|
|
1447 * or loopback. |
|
|
1448 */ |
|
|
1449 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) |
|
|
1450 continue; |
|
|
1451 if ((ifreq.ifr_flags & |
|
|
1452 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP)) |
|
|
1453 != (IFF_UP|IFF_BROADCAST)) |
|
|
1454 continue; |
|
|
1455 /* |
|
|
1456 * Get its netmask and check that it's on the right subnet. |
|
|
1457 */ |
|
|
1458 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) |
|
|
1459 continue; |
|
|
1460 mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; |
|
|
1461 if ((ipaddr & mask) != (ina & mask)) |
|
|
1462 continue; |
|
|
1463 |
|
|
1464 break; |
|
|
1465 } |
|
|
1466 } |
|
|
1467 |
|
|
1468 if (ifr >= ifend) |
|
|
1469 return 0; |
|
|
1470 syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name); |
|
|
1471 |
|
|
1472 /* |
|
|
1473 * Now scan through again looking for a link-level address |
|
|
1474 * for this interface. |
|
|
1475 */ |
|
|
1476 ifp = ifr; |
|
|
1477 for (ifr = ifc.ifc_req; ifr < ifend; ) { |
|
|
1478 if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 |
|
|
1479 && ifr->ifr_addr.sa_family == AF_LINK) { |
|
|
1480 /* |
|
|
1481 * Found the link-level address - copy it out |
|
|
1482 */ |
|
|
1483 dla = (struct sockaddr_dl *) &ifr->ifr_addr; |
|
|
1484 BCOPY(dla, hwaddr, dla->sdl_len); |
|
|
1485 return 1; |
|
|
1486 } |
|
|
1487 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr |
|
|
1488 + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr))); |
|
|
1489 } |
|
|
1490 |
|
|
1491 return 0; |
|
|
1492 } |
|
|
1493 |
|
|
1494 //========================================================================== |
|
|
1495 /* |
|
|
1496 * Return user specified netmask, modified by any mask we might determine |
|
|
1497 * for address `addr' (in network byte order). |
|
|
1498 * Here we scan through the system's list of interfaces, looking for |
|
|
1499 * any non-point-to-point interfaces which might appear to be on the same |
|
|
1500 * network as `addr'. If we find any, we OR in their netmask to the |
|
|
1501 * user-specified netmask. |
|
|
1502 */ |
|
|
1503 u_int32_t |
|
|
1504 GetMask(addr) |
|
|
1505 u_int32_t addr; |
|
|
1506 { |
|
|
1507 u_int32_t mask, nmask, ina; |
|
|
1508 struct ifreq *ifr, *ifend, ifreq; |
|
|
1509 struct ifconf ifc; |
|
|
1510 struct ifreq ifs[MAX_IFS]; |
|
|
1511 |
|
|
1512 addr = ntohl(addr); |
|
|
1513 if (IN_CLASSA(addr)) /* determine network mask for address class */ |
|
|
1514 nmask = IN_CLASSA_NET; |
|
|
1515 else if (IN_CLASSB(addr)) |
|
|
1516 nmask = IN_CLASSB_NET; |
|
|
1517 else |
|
|
1518 nmask = IN_CLASSC_NET; |
|
|
1519 /* class D nets are disallowed by bad_ip_adrs */ |
|
|
1520 mask = netmask | htonl(nmask); |
|
|
1521 |
|
|
1522 /* |
|
|
1523 * Scan through the system's network interfaces. |
|
|
1524 */ |
|
|
1525 ifc.ifc_len = sizeof(ifs); |
|
|
1526 ifc.ifc_req = ifs; |
|
|
1527 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { |
|
|
1528 syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m"); |
|
|
1529 return mask; |
|
|
1530 } |
|
|
1531 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); |
|
|
1532 for (ifr = ifc.ifc_req; ifr < ifend; |
|
|
1533 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr |
|
|
1534 + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) { |
|
|
1535 /* |
|
|
1536 * Check the interface's internet address. |
|
|
1537 */ |
|
|
1538 if (ifr->ifr_addr.sa_family != AF_INET) |
|
|
1539 continue; |
|
|
1540 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; |
|
|
1541 if ((ntohl(ina) & nmask) != (addr & nmask)) |
|
|
1542 continue; |
|
|
1543 /* |
|
|
1544 * Check that the interface is up, and not point-to-point or loopback. |
|
|
1545 */ |
|
|
1546 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); |
|
|
1547 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) |
|
|
1548 continue; |
|
|
1549 if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) |
|
|
1550 != IFF_UP) |
|
|
1551 continue; |
|
|
1552 /* |
|
|
1553 * Get its netmask and OR it into our mask. |
|
|
1554 */ |
|
|
1555 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) |
|
|
1556 continue; |
|
|
1557 mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr; |
|
|
1558 } |
|
|
1559 |
|
|
1560 return mask; |
|
|
1561 } |
|
|
1562 |
|
|
1563 //========================================================================== |
|
|
1564 /* |
|
|
1565 * Use the hostid as part of the random number seed. |
|
|
1566 */ |
|
|
1567 int |
|
|
1568 get_host_seed() |
|
|
1569 { |
|
|
1570 //db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1571 #ifndef __ECOS |
|
|
1572 return gethostid(); |
|
|
1573 #endif |
|
|
1574 return 0; |
|
|
1575 } |
|
|
1576 |
|
|
1577 //===================================================================== |
|
|
1578 // PAP stubs |
|
|
1579 // |
|
|
1580 // When omitting PAP, these fill in the dangling references from auth.c |
|
|
1581 // |
|
|
1582 |
|
|
1583 #ifndef CYGPKG_PPP_PAP |
|
|
1584 |
|
|
1585 void |
|
|
1586 upap_authwithpeer(unit, user, password) |
|
|
1587 int unit; |
|
|
1588 char *user, *password; |
|
|
1589 { |
|
|
1590 unit=unit; |
|
|
1591 user=user; |
|
|
1592 password=password; |
|
|
1593 } |
|
|
1594 |
|
|
1595 void |
|
|
1596 upap_authpeer(unit) |
|
|
1597 int unit; |
|
|
1598 { |
|
|
1599 unit=unit; |
|
|
1600 } |
|
|
1601 |
|
|
1602 #endif |
|
|
1603 |
|
|
1604 //===================================================================== |
|
|
1605 // CHAP stubs |
|
|
1606 // |
|
|
1607 // When omitting CHAP, these fill in the dangling references from auth.c |
|
|
1608 // |
|
|
1609 |
|
|
1610 #ifndef CYGPKG_PPP_CHAP |
|
|
1611 |
|
|
1612 void |
|
|
1613 ChapAuthWithPeer(unit, our_name, digest) |
|
|
1614 int unit; |
|
|
1615 char *our_name; |
|
|
1616 int digest; |
|
|
1617 { |
|
|
1618 unit=unit; |
|
|
1619 our_name=our_name; |
|
|
1620 digest=digest; |
|
|
1621 } |
|
|
1622 |
|
|
1623 void |
|
|
1624 ChapAuthPeer(unit, our_name, digest) |
|
|
1625 int unit; |
|
|
1626 char *our_name; |
|
|
1627 int digest; |
|
|
1628 { |
|
|
1629 unit=unit; |
|
|
1630 our_name=our_name; |
|
|
1631 digest=digest; |
|
|
1632 } |
|
|
1633 |
|
|
1634 #endif |
|
|
1635 |
|
|
1636 //===================================================================== |
|
|
1637 // eCos API |
|
|
1638 |
|
|
1639 externC cyg_int32 cyg_ppp_options_init( cyg_ppp_options_t *options ) |
|
|
1640 { |
|
|
1641 if( options == NULL ) |
|
|
1642 return -1; |
|
|
1643 |
|
|
1644 options->debug = 0; |
|
|
1645 options->kdebugflag = 0; |
|
|
1646 options->default_route = 1; |
|
|
1647 options->modem = 0; |
|
|
1648 options->flowctl = CYG_PPP_FLOWCTL_HARDWARE; |
|
|
1649 options->refuse_pap = 0; |
|
|
1650 options->refuse_chap = 0; |
|
|
1651 |
|
|
1652 options->baud = CYGNUM_SERIAL_BAUD_115200; |
|
|
1653 |
|
|
1654 options->idle_time_limit = 1*60; |
|
|
1655 options->maxconnect = 0; |
|
|
1656 |
|
|
1657 options->our_address = 0; |
|
|
1658 options->his_address = 0; |
|
|
1659 |
|
|
1660 options->script = NULL; |
|
|
1661 |
|
|
1662 strncpy( options->user, CYGPKG_PPP_AUTH_DEFAULT_USER, MAXNAMELEN ); |
|
|
1663 strncpy( options->passwd, CYGPKG_PPP_AUTH_DEFAULT_PASSWD, MAXSECRETLEN ); |
|
|
1664 |
|
|
1665 return 0; |
|
|
1666 } |
|
|
1667 |
|
|
1668 // ------------------------------------------------------------------------- |
|
|
1669 |
|
|
1670 |
|
|
1671 #define CYGNUM_PPP_PPPD_THREAD_STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL+0x1000) |
|
|
1672 |
|
|
1673 static char cyg_pppd_stack[CYGNUM_PPP_PPPD_THREAD_STACK_SIZE]; |
|
|
1674 static cyg_thread cyg_pppd_thread_obj; |
|
|
1675 |
|
|
1676 static char cyg_ppp_tx_thread_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; |
|
|
1677 static cyg_thread cyg_ppp_tx_thread_obj; |
|
|
1678 |
|
|
1679 |
|
|
1680 externC void cyg_pppd_main(CYG_ADDRWORD arg); |
|
|
1681 |
|
|
1682 |
|
|
1683 externC cyg_ppp_handle_t cyg_ppp_up( const char *devnam_arg, |
|
|
1684 const cyg_ppp_options_t *options ) |
|
|
1685 { |
|
|
1686 |
|
|
1687 if( options == NULL || phase != PHASE_DEAD ) |
|
|
1688 return 0; |
|
|
1689 |
|
|
1690 strncpy( devnam, devnam_arg, PATH_MAX ); |
|
|
1691 |
|
|
1692 ppp_tty.options = options; |
|
|
1693 |
|
|
1694 // Start the PPPD thread |
|
|
1695 cyg_thread_create(CYGNUM_PPP_PPPD_THREAD_PRIORITY, |
|
|
1696 cyg_pppd_main, |
|
|
1697 (CYG_ADDRWORD)&ppp_tty, |
|
|
1698 "PPPD", |
|
|
1699 &cyg_pppd_stack[0], |
|
|
1700 CYGNUM_PPP_PPPD_THREAD_STACK_SIZE, |
|
|
1701 &ppp_tty.pppd_thread, |
|
|
1702 &cyg_pppd_thread_obj |
|
|
1703 ); |
|
|
1704 cyg_thread_resume(ppp_tty.pppd_thread); |
|
|
1705 |
|
|
1706 // Start the TX thread |
|
|
1707 cyg_semaphore_init( &ppp_tty.tx_sem, 0 ); |
|
|
1708 |
|
|
1709 cyg_thread_create(CYGNUM_PPP_PPPD_THREAD_PRIORITY+1, |
|
|
1710 cyg_ppp_tx_thread, |
|
|
1711 (CYG_ADDRWORD)&ppp_tty, |
|
|
1712 "PPP Tx Thread", |
|
|
1713 &cyg_ppp_tx_thread_stack[0], |
|
|
1714 sizeof(cyg_ppp_tx_thread_stack), |
|
|
1715 &ppp_tty.tx_thread, |
|
|
1716 &cyg_ppp_tx_thread_obj |
|
|
1717 ); |
|
|
1718 cyg_thread_resume(ppp_tty.tx_thread); |
|
|
1719 |
|
|
1720 // Wait for the PPPD thread to get going and start the PPP |
|
|
1721 // initialization phase. |
|
|
1722 while(phase == PHASE_DEAD ) |
|
|
1723 cyg_thread_delay(100); |
|
|
1724 |
|
|
1725 return (cyg_ppp_handle_t)&ppp_tty; |
|
|
1726 } |
|
|
1727 |
|
|
1728 // ------------------------------------------------------------------------- |
|
|
1729 |
|
|
1730 externC char **script; |
|
|
1731 |
|
|
1732 externC void cyg_ppp_options_install( const cyg_ppp_options_t *options ) |
|
|
1733 { |
|
|
1734 debug = options->debug; |
|
|
1735 kdebugflag = options->kdebugflag; |
|
|
1736 |
|
|
1737 modem = options->modem; |
|
|
1738 flowctl = options->flowctl; |
|
|
1739 refuse_pap = options->refuse_pap; |
|
|
1740 refuse_chap = options->refuse_chap; |
|
|
1741 |
|
|
1742 inspeed = options->baud; |
|
|
1743 |
|
|
1744 idle_time_limit = options->idle_time_limit; |
|
|
1745 maxconnect = options->maxconnect; |
|
|
1746 |
|
|
1747 { |
|
|
1748 ipcp_options *wo = &ipcp_wantoptions[0]; |
|
|
1749 |
|
|
1750 wo->ouraddr = options->our_address; |
|
|
1751 wo->hisaddr = options->his_address; |
|
|
1752 |
|
|
1753 wo->default_route = options->default_route; |
|
|
1754 |
|
|
1755 } |
|
|
1756 |
|
|
1757 script = options->script; |
|
|
1758 |
|
|
1759 strncpy( user, &options->user[0], MAXNAMELEN ); |
|
|
1760 strncpy( passwd, &options->passwd[0], MAXSECRETLEN ); |
|
|
1761 |
|
|
1762 } |
|
|
1763 |
|
|
1764 // ------------------------------------------------------------------------- |
|
|
1765 |
|
|
1766 externC cyg_int32 cyg_ppp_down( const cyg_ppp_handle_t handle ) |
|
|
1767 { |
|
|
1768 if( phase != PHASE_DEAD ) |
|
|
1769 { |
|
|
1770 externC int kill_link; |
|
|
1771 kill_link = 1; |
|
|
1772 cyg_thread_release( ppp_tty.pppd_thread ); |
|
|
1773 ppp_tty.pppd_wakeup = 1; |
|
|
1774 return 0; |
|
|
1775 } |
|
|
1776 else |
|
|
1777 return -1; |
|
|
1778 } |
|
|
1779 |
|
|
1780 // ------------------------------------------------------------------------- |
|
|
1781 |
|
|
1782 externC cyg_int32 cyg_ppp_wait_up( cyg_ppp_handle_t handle ) |
|
|
1783 { |
|
|
1784 while(!( (phase == PHASE_NETWORK && ifaddrs[0] != 0) || |
|
|
1785 phase == PHASE_DEAD ) ) |
|
|
1786 cyg_thread_delay(100); |
|
|
1787 |
|
|
1788 return phase == PHASE_NETWORK ? 0 : -1; |
|
|
1789 } |
|
|
1790 |
|
|
1791 // ------------------------------------------------------------------------- |
|
|
1792 |
|
|
1793 externC void cyg_ppp_wait_down( cyg_ppp_handle_t handle ) |
|
|
1794 { |
|
|
1795 while( ppp_tty.tx_thread_running || ppp_tty.pppd_thread_running ) |
|
|
1796 cyg_thread_delay(100); |
|
|
1797 |
|
|
1798 cyg_thread_delete( ppp_tty.tx_thread ); |
|
|
1799 cyg_thread_delete( ppp_tty.pppd_thread ); |
|
|
1800 } |
|
|
1801 |
|
|
1802 //===================================================================== |
|
|
1803 // eCos extras |
|
|
1804 |
|
|
1805 void syslog( int level, char *fmt, ... ) |
|
|
1806 { |
|
|
1807 va_list ap; |
|
|
1808 int ret; |
|
|
1809 |
|
|
1810 #ifdef CYGPKG_PPP_DEBUG_WARN_ONLY |
|
|
1811 if(!( level == LOG_ERR || |
|
|
1812 level == LOG_WARNING )) |
|
|
1813 return; |
|
|
1814 #endif |
|
|
1815 |
|
|
1816 va_start(ap, fmt); |
|
|
1817 diag_printf("SYSLOG %02x: ",level); |
|
|
1818 ret = diag_vprintf(fmt, ap); |
|
|
1819 diag_printf("\n"); |
|
|
1820 va_end(ap); |
|
|
1821 } |
|
|
1822 |
|
|
1823 //===================================================================== |
|
|
1824 |
|
|
1825 int gettimeofday(struct timeval *tv, struct timezone *tz) |
|
|
1826 { |
|
|
1827 cyg_tick_count_t time = cyg_current_time(); |
|
|
1828 |
|
|
1829 tv->tv_sec = time/CYGNUM_HAL_RTC_DENOMINATOR; |
|
|
1830 tv->tv_usec = (time%CYGNUM_HAL_RTC_DENOMINATOR)*10000; |
|
|
1831 |
|
|
1832 // db_printf("%s: %d %d\n", __PRETTY_FUNCTION__, tv->tv_sec, tv->tv_usec); |
|
|
1833 |
|
|
1834 return 0; |
|
|
1835 } |
|
|
1836 |
|
|
1837 //===================================================================== |
|
|
1838 |
|
|
1839 char *crypt (const char *key, const char *salt) |
|
|
1840 { |
|
|
1841 static char res[13]; |
|
|
1842 |
|
|
1843 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1844 |
|
|
1845 return res; |
|
|
1846 } |
|
|
1847 |
|
|
1848 |
|
|
1849 //===================================================================== |
|
|
1850 /* |
|
|
1851 * Substitute procedures for those systems which don't have |
|
|
1852 * drand48 et al. |
|
|
1853 */ |
|
|
1854 |
|
|
1855 double |
|
|
1856 drand48(void) |
|
|
1857 { |
|
|
1858 return (double)rand() / (double)0x7fffffffL; /* 2**31-1 */ |
|
|
1859 } |
|
|
1860 |
|
|
1861 long |
|
|
1862 mrand48(void) |
|
|
1863 { |
|
|
1864 return rand(); |
|
|
1865 } |
|
|
1866 |
|
|
1867 void |
|
|
1868 srand48(long seedval) |
|
|
1869 { |
|
|
1870 srand(seedval); |
|
|
1871 } |
|
|
1872 |
|
|
1873 |
|
|
1874 //===================================================================== |
|
|
1875 |
|
|
1876 #if 0 |
|
|
1877 |
|
|
1878 #undef MD5Init |
|
|
1879 #undef MD5Update |
|
|
1880 #undef MD5Final |
|
|
1881 |
|
|
1882 #include <sys/types.h> |
|
|
1883 |
|
|
1884 #include <sys/md5.h> |
|
|
1885 |
|
|
1886 |
|
|
1887 void cyg_MD5Init( MD5_CTX *ctx ); |
|
|
1888 void cyg_MD5Update (MD5_CTX *ctx, const unsigned char *buf, unsigned int size); |
|
|
1889 void cyg_MD5Final (unsigned char hash[16], MD5_CTX *ctx); |
|
|
1890 |
|
|
1891 |
|
|
1892 void cyg_ppp_MD5Init( MD5_CTX *ctx ) |
|
|
1893 { |
|
|
1894 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1895 cyg_MD5Init( ctx ); |
|
|
1896 return; |
|
|
1897 } |
|
|
1898 |
|
|
1899 void cyg_ppp_MD5Update (MD5_CTX *ctx, const unsigned char *buf, unsigned int size) |
|
|
1900 { |
|
|
1901 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1902 cyg_MD5Update( ctx, buf, size ); |
|
|
1903 return; |
|
|
1904 } |
|
|
1905 |
|
|
1906 void cyg_ppp_MD5Final (unsigned char hash[16], MD5_CTX *ctx) |
|
|
1907 { |
|
|
1908 db_printf("%s called\n", __PRETTY_FUNCTION__); |
|
|
1909 cyg_MD5Final( hash, ctx ); |
|
|
1910 return; |
|
|
1911 } |
|
|
1912 |
|
|
1913 #endif |
|
|
1914 |
|
|
1915 //===================================================================== |
|
|
1916 // End of sys-ecos.c |
|
|
1917 |
|
|
1918 |