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 extern u_int32_t netmask; /* IP netmask to set on interface */
173
174 //==========================================================================
175 /*
176 * sys_init - System-dependent initialization.
177 */
178 void
sys_init()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
sys_cleanup()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
sys_exit(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
sys_close()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
sys_check_options()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
ppp_available()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
establish_ppp(cyg_io_handle_t handle)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
restore_loop()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
disestablish_ppp(cyg_io_handle_t handle)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
clean_check()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
set_up_tty(cyg_io_handle_t handle,int local)387 set_up_tty(cyg_io_handle_t handle, int local)
388 {
389 cyg_serial_info_t cfg;
390 int err;
391 cyg_uint32 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
restore_tty(cyg_io_handle_t handle)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
setdtr(fd,on)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
output(unit,p,len)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
wait_input_alarm(cyg_handle_t alarm,cyg_addrword_t data)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
cyg_ppp_serial_callback(cyg_serial_line_status_t * s,CYG_ADDRWORD priv)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 ppp_tty.carrier_detected = 0;
542 kill_link = 1;
543 cyg_thread_release( ppp_tty.pppd_thread );
544 ppp_tty.pppd_wakeup = 1;
545 }
546 else
547 {
548 // CD up
549 ppp_tty.carrier_detected = 1;
550 }
551 }
552 }
553 #endif
554
cyg_ppp_tx_thread(CYG_ADDRWORD arg)555 static void cyg_ppp_tx_thread(CYG_ADDRWORD arg)
556 {
557 ppp_tty.tx_thread_running = true;
558
559 // Wait for the PPPD thread to get going and start the PPP
560 // initialization phase.
561 while(phase == PHASE_DEAD )
562 cyg_thread_delay(100);
563
564 // Now loop until the link goes back down.
565 while( phase != PHASE_DEAD )
566 {
567 cyg_semaphore_wait( &ppp_tty.tx_sem );
568
569 if( phase == PHASE_DEAD )
570 break;
571
572 // Call into PPP driver to get transmissions going. This is
573 // only called if some other thread has failed to transmit all
574 // of a packet due to a full buffer, or flow control.
575
576 cyg_ppp_pppstart( &ppp_tty );
577 }
578
579 db_printf("%s exiting\n", __PRETTY_FUNCTION__);
580 ppp_tty.tx_thread_running = false;
581 cyg_thread_exit();
582 }
583
584 #endif
585
586
587 //==========================================================================
588 /*
589 * wait_input - wait until there is data available on ttyfd,
590 * for the length of time specified by *timo (indefinite
591 * if timo is NULL).
592 */
593 void
wait_input(timo)594 wait_input(timo)
595 struct timeval *timo;
596 {
597 // If there are any packets still waiting on the input queue then
598 // return immediately to let the PPPD handle them.
599 if (cyg_ppp_pppcheck(&ppp_tty) != 0)
600 return;
601
602 if( timo != NULL )
603 {
604 cyg_tick_count_t trigger = timo->tv_sec*ppp_rtc_resolution.divisor;
605
606 // If the timeval has a microseconds value, just add another
607 // second on to the trigger time. These are after all just
608 // timeouts, not accurate timings, so a bit of imprecision
609 // will not hurt.
610 if( timo->tv_usec != 0 )
611 trigger += ppp_rtc_resolution.divisor;
612
613 trigger += cyg_current_time();
614
615 // We set the alarm to retrigger after a second. This is in
616 // case it catches cyg_io_read() at an uninterruptible
617 // point. The alarm is disabled as soon as the read returns,
618 // so the retrigger will usually not happen.
619 cyg_alarm_initialize( ppp_tty.alarm,
620 trigger,
621 ppp_rtc_resolution.divisor );
622 }
623
624 for(;;)
625 {
626 int s;
627 cyg_uint32 len = 1;
628 Cyg_ErrNo err;
629 cyg_serial_buf_info_t info;
630 cyg_uint32 ilen = sizeof(info);
631
632 #if 1
633 // Work out how many bytes are waiting in the serial device
634 // buffer and read them all at once. If there are none, we
635 // just wait for a single character to arrive.
636
637 if( cyg_io_get_config( ppp_tty.t_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO,
638 &info, &ilen ) == 0 && info.rx_count > 1 )
639 {
640 len = info.rx_count-1;
641 if( len > sizeof(inbuf) )
642 len = sizeof(inbuf);
643 }
644 #endif
645
646 if( timo != NULL )
647 cyg_alarm_enable( ppp_tty.alarm );
648
649 err = cyg_io_read( ppp_handle, &inbuf, &len );
650
651 if( timo != NULL )
652 cyg_alarm_disable( ppp_tty.alarm );
653
654 // db_printf("read: err %d len %d byte %02x\n",err,len,inbuf[0]);
655
656 if( err == 0 )
657 {
658 int i;
659
660 // Pass all input data to PPP driver for analysis. If this
661 // turns out to be for the PPPD, it will call
662 // pppasyncctlp() which in turn will set
663 // ppp_tty.pppd_wakeup. We detect that on return from
664 // pppinput() and return to the caller to do pppd
665 // processing.
666
667 s = splsoftnet();
668
669 for( i = 0; i < len; i++ )
670 {
671 err = cyg_ppp_pppinput( inbuf[i], &ppp_tty );
672
673 if( err != 0 )
674 syslog( LOG_ERR, "pppinput error: %d", err);
675
676 }
677
678 splx(s);
679
680 }
681 else if( err != -EINTR )
682 syslog( LOG_ERR, "Read error: %d",err);
683
684 if( ppp_tty.pppd_wakeup )
685 {
686 ppp_tty.pppd_wakeup = 0;
687 break;
688 }
689 }
690 }
691
692 //==========================================================================
693 /*
694 * wait_time - wait for a given length of time or until a
695 * signal is received.
696 */
697 void
wait_time(timo)698 wait_time(timo)
699 struct timeval *timo;
700 {
701 db_printf("%s called\n", __PRETTY_FUNCTION__);
702 }
703
704
705 //==========================================================================
706 /*
707 * read_packet - get a PPP packet from the serial device.
708 */
709 int
read_packet(buf)710 read_packet(buf)
711 u_char *buf;
712 {
713 int err;
714 struct uio uio;
715 struct iovec iov;
716 int len = PPP_MTU + PPP_HDRLEN;
717 int s;
718
719 //db_printf("%s called\n", __PRETTY_FUNCTION__);
720
721 iov.iov_base = buf;
722 iov.iov_len = len;
723 uio.uio_iov = &iov;
724 uio.uio_iovcnt = 1;
725 uio.uio_resid = len;
726 uio.uio_segflg = UIO_USERSPACE;
727 uio.uio_rw = UIO_READ;
728
729 s = splsoftnet();
730
731 err = cyg_ppp_pppread( &ppp_tty, &uio, 0 );
732
733 splx(s);
734
735 if( err == EWOULDBLOCK )
736 return -1;
737
738 if( err != 0 )
739 {
740 syslog(LOG_ERR, "pppread: %d",err);
741 die(1);
742 }
743
744 len -= uio.uio_resid;
745
746 return len;
747 }
748
749 //==========================================================================
750 /*
751 * ppp_send_config - configure the transmit characteristics of
752 * the ppp interface.
753 */
754 void
ppp_send_config(unit,mtu,asyncmap,pcomp,accomp)755 ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
756 int unit, mtu;
757 u_int32_t asyncmap;
758 int pcomp, accomp;
759 {
760 u_int x;
761 struct ifreq ifr;
762 int err;
763 int s;
764
765 // db_printf("%s: unit %d mtu %d asyncmap %08x pcomp %08x accomp %08x\n", __PRETTY_FUNCTION__,
766 // unit,mtu,asyncmap,pcomp,accomp);
767
768 strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
769 ifr.ifr_mtu = mtu;
770 if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
771 syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %d",errno);
772 quit();
773 }
774
775
776 s = splsoftnet();
777
778 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSASYNCMAP, (caddr_t) &asyncmap, 0)) < 0) {
779 syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %d",err);
780 }
781
782 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) < 0) {
783 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err);
784 }
785 x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
786 x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
787 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) < 0) {
788 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err);
789 }
790
791 splx(s);
792 }
793
794
795 //==========================================================================
796 /*
797 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
798 */
799 void
ppp_set_xaccm(unit,accm)800 ppp_set_xaccm(unit, accm)
801 int unit;
802 ext_accm accm;
803 {
804 int error;
805 int s;
806
807 //db_printf("%s called\n", __PRETTY_FUNCTION__);
808
809 s = splsoftnet();
810
811 error = cyg_ppp_ppptioctl( &ppp_tty, PPPIOCSXASYNCMAP, (caddr_t)accm, 0 );
812
813 splx(s);
814
815 if( error != 0 )
816 syslog(LOG_WARNING, "ioctl(set extended ACCM): %d",error);
817 }
818
819
820 //==========================================================================
821 /*
822 * ppp_recv_config - configure the receive-side characteristics of
823 * the ppp interface.
824 */
825 void
ppp_recv_config(unit,mru,asyncmap,pcomp,accomp)826 ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
827 int unit, mru;
828 u_int32_t asyncmap;
829 int pcomp, accomp;
830 {
831 int x;
832 int err;
833 int s;
834
835 s = splsoftnet();
836
837 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSMRU, (caddr_t) &mru, 0)) < 0) {
838 syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %d",err);
839 }
840 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap, 0)) < 0) {
841 syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %d",err);
842 }
843 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) < 0) {
844 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err);
845 }
846 x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
847 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) < 0) {
848 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err);
849 }
850
851 splx(s);
852 }
853
854 //==========================================================================
855 /*
856 * ccp_test - ask kernel whether a given compression method
857 * is acceptable for use. Returns 1 if the method and parameters
858 * are OK, 0 if the method is known but the parameters are not OK
859 * (e.g. code size should be reduced), or -1 if the method is unknown.
860 */
861 int
ccp_test(unit,opt_ptr,opt_len,for_transmit)862 ccp_test(unit, opt_ptr, opt_len, for_transmit)
863 int unit, opt_len, for_transmit;
864 u_char *opt_ptr;
865 {
866 struct ppp_option_data data;
867 int s;
868
869 data.ptr = opt_ptr;
870 data.length = opt_len;
871 data.transmit = for_transmit;
872 //db_printf("%s called\n", __PRETTY_FUNCTION__);
873
874 s = splsoftnet();
875
876 errno = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSCOMPRESS, (caddr_t) &data, 0 );
877
878 splx(s);
879
880 if (errno == 0)
881 return 1;
882 else return (errno == ENOBUFS)? 0: -1;
883
884 }
885
886 //==========================================================================
887 /*
888 * ccp_flags_set - inform kernel about the current state of CCP.
889 */
890 void
ccp_flags_set(unit,isopen,isup)891 ccp_flags_set(unit, isopen, isup)
892 int unit, isopen, isup;
893 {
894 int x;
895
896 int err;
897 //db_printf("%s called\n", __PRETTY_FUNCTION__);
898 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) != 0) {
899 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err);
900 return;
901 }
902 x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
903 x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
904 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x,0)) != 0)
905 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err);
906 }
907
908 //==========================================================================
909 /*
910 * ccp_fatal_error - returns 1 if decompression was disabled as a
911 * result of an error detected after decompression of a packet,
912 * 0 otherwise. This is necessary because of patent nonsense.
913 */
914 int
ccp_fatal_error(unit)915 ccp_fatal_error(unit)
916 int unit;
917 {
918 int x;
919 int err;
920
921 db_printf("%s called\n", __PRETTY_FUNCTION__);
922 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) != 0) {
923 syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %d",err);
924 return 0;
925 }
926 return x & SC_DC_FERROR;
927 }
928
929 //==========================================================================
930 /*
931 * get_idle_time - return how long the link has been idle.
932 */
933 int
get_idle_time(u,ip)934 get_idle_time(u, ip)
935 int u;
936 struct ppp_idle *ip;
937 {
938 return cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGIDLE, (caddr_t)ip, 0) == 0;
939 }
940
941
942 //==========================================================================
943
944 #ifdef PPP_FILTER
945 /*
946 * set_filters - transfer the pass and active filters to the kernel.
947 */
948 int
set_filters(pass,active)949 set_filters(pass, active)
950 struct bpf_program *pass, *active;
951 {
952 int ret = 1;
953
954 db_printf("%s called\n", __PRETTY_FUNCTION__);
955 if (pass->bf_len > 0) {
956 if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) {
957 syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m");
958 ret = 0;
959 }
960 }
961 if (active->bf_len > 0) {
962 if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) {
963 syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m");
964 ret = 0;
965 }
966 }
967 return ret;
968 }
969 #endif
970
971 //==========================================================================
972 /*
973 * sifvjcomp - config tcp header compression
974 */
975 int
sifvjcomp(u,vjcomp,cidcomp,maxcid)976 sifvjcomp(u, vjcomp, cidcomp, maxcid)
977 int u, vjcomp, cidcomp, maxcid;
978 {
979 u_int x;
980 int err;
981
982 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCGFLAGS, (caddr_t) &x, 0)) != 0) {
983 syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %d",err);
984 return 0;
985 }
986 x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
987 x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
988 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSFLAGS, (caddr_t) &x, 0)) != 0) {
989 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %d",err);
990 return 0;
991 }
992 if (vjcomp && ((err=cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSMAXCID, (caddr_t) &maxcid, 0)) != 0)) {
993 syslog(LOG_ERR, "ioctl(PPPIOCSMAXCID): %d",err);
994 return 0;
995 }
996 return 1;
997 }
998
999 //==========================================================================
1000 /*
1001 * sifup - Config the interface up and enable IP packets to pass.
1002 */
1003 int
sifup(u)1004 sifup(u)
1005 int u;
1006 {
1007 struct ifreq ifr;
1008
1009 //db_printf("%s called\n", __PRETTY_FUNCTION__);
1010 strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1011 if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1012 syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
1013 return 0;
1014 }
1015 ifr.ifr_flags |= IFF_UP;
1016 if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1017 syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
1018 return 0;
1019 }
1020 if_is_up = 1;
1021 return 1;
1022 }
1023
1024 //==========================================================================
1025 /*
1026 * sifnpmode - Set the mode for handling packets for a given NP.
1027 */
1028 int
sifnpmode(u,proto,mode)1029 sifnpmode(u, proto, mode)
1030 int u;
1031 int proto;
1032 enum NPmode mode;
1033 {
1034 struct npioctl npi;
1035
1036 //db_printf("%s called\n", __PRETTY_FUNCTION__);
1037 npi.protocol = proto;
1038 npi.mode = mode;
1039 {
1040 int err;
1041
1042 if ((err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSNPMODE, (caddr_t)&npi, 0)) < 0) {
1043 syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %d", proto, mode,err);
1044 return 0;
1045 }
1046 }
1047
1048 return 1;
1049 }
1050
1051 //==========================================================================
1052 /*
1053 * sifdown - Config the interface down and disable IP.
1054 */
1055 int
sifdown(u)1056 sifdown(u)
1057 int u;
1058 {
1059 struct ifreq ifr;
1060 int rv;
1061 struct npioctl npi;
1062
1063 db_printf("%s called\n", __PRETTY_FUNCTION__);
1064 rv = 1;
1065 npi.protocol = PPP_IP;
1066 npi.mode = NPMODE_ERROR;
1067 {
1068 int err = cyg_ppp_ppptioctl(&ppp_tty, PPPIOCSNPMODE, (caddr_t) &npi, 0);
1069 if( err < 0 )
1070 syslog(LOG_WARNING, "ioctl(PPPIOCSNPMODE): %d",err);
1071 }
1072 strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
1073 if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
1074 syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
1075 rv = 0;
1076 } else {
1077 ifr.ifr_flags &= ~IFF_UP;
1078 if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
1079 syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
1080 rv = 0;
1081 } else
1082 if_is_up = 0;
1083 }
1084 return rv;
1085 return 0;
1086 }
1087
1088 //==========================================================================
1089 /*
1090 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
1091 * if it exists.
1092 */
1093 #define SET_SA_FAMILY(addr, family) \
1094 BZERO((char *) &(addr), sizeof(addr)); \
1095 addr.sa_family = (family); \
1096 addr.sa_len = sizeof(addr);
1097
1098 //==========================================================================
1099 /*
1100 * sifaddr - Config the interface IP addresses and netmask.
1101 */
1102 int
sifaddr(u,o,h,m)1103 sifaddr(u, o, h, m)
1104 int u;
1105 u_int32_t o, h, m;
1106 {
1107 struct ifaliasreq ifra;
1108 struct ifreq ifr;
1109
1110 //db_printf("%s called\n", __PRETTY_FUNCTION__);
1111 strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1112 SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1113 ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1114 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1115 ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1116 if (m != 0) {
1117 SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
1118 ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
1119 } else
1120 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1121 BZERO(&ifr, sizeof(ifr));
1122 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1123 if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
1124 if (errno != EADDRNOTAVAIL)
1125 syslog(LOG_WARNING, "Couldn't remove interface address: %d",errno);
1126 }
1127 if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
1128 if (errno != EEXIST) {
1129 syslog(LOG_ERR, "Couldn't set interface address: %d",errno);
1130 return 0;
1131 }
1132 syslog(LOG_WARNING,
1133 "Couldn't set interface address: Address %s already exists",
1134 ip_ntoa(o));
1135 }
1136 ifaddrs[0] = o;
1137 ifaddrs[1] = h;
1138 return 1;
1139 }
1140
1141 //==========================================================================
1142 /*
1143 * cifaddr - Clear the interface IP addresses, and delete routes
1144 * through the interface if possible.
1145 */
1146 int
cifaddr(u,o,h)1147 cifaddr(u, o, h)
1148 int u;
1149 u_int32_t o, h;
1150 {
1151 struct ifaliasreq ifra;
1152
1153 db_printf("%s called\n", __PRETTY_FUNCTION__);
1154 ifaddrs[0] = 0;
1155 strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1156 SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
1157 ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
1158 SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
1159 ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
1160 BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
1161 if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
1162 if (errno != EADDRNOTAVAIL)
1163 syslog(LOG_WARNING, "Couldn't delete interface address: %m");
1164 return 0;
1165 }
1166 return 1;
1167 }
1168
1169 //==========================================================================
1170 /*
1171 * sifdefaultroute - assign a default route through the address given.
1172 */
1173 int
sifdefaultroute(u,l,g)1174 sifdefaultroute(u, l, g)
1175 int u;
1176 u_int32_t l, g;
1177 {
1178 db_printf("%s called\n", __PRETTY_FUNCTION__);
1179 return dodefaultroute(g, 's');
1180 }
1181
1182 //==========================================================================
1183 /*
1184 * cifdefaultroute - delete a default route through the address given.
1185 */
1186 int
cifdefaultroute(u,l,g)1187 cifdefaultroute(u, l, g)
1188 int u;
1189 u_int32_t l, g;
1190 {
1191 db_printf("%s called\n", __PRETTY_FUNCTION__);
1192 return dodefaultroute(g, 'c');
1193 }
1194
1195 //==========================================================================
1196 /*
1197 * dodefaultroute - talk to a routing socket to add/delete a default route.
1198 */
1199 static int
dodefaultroute(g,cmd)1200 dodefaultroute(g, cmd)
1201 u_int32_t g;
1202 int cmd;
1203 {
1204 int routes;
1205 struct {
1206 struct rt_msghdr hdr;
1207 struct sockaddr_in dst;
1208 struct sockaddr_in gway;
1209 struct sockaddr_in mask;
1210 } rtmsg;
1211
1212 db_printf("%s %08x %c\n", __PRETTY_FUNCTION__,g,cmd);
1213 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1214 syslog(LOG_ERR, "Couldn't %s default route: socket: %d",
1215 cmd=='s'? "add": "delete",errno);
1216 return 0;
1217 }
1218
1219 memset(&rtmsg, 0, sizeof(rtmsg));
1220 rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE;
1221 rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
1222 rtmsg.hdr.rtm_version = RTM_VERSION;
1223 rtmsg.hdr.rtm_seq = ++rtm_seq;
1224 rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
1225 rtmsg.dst.sin_len = sizeof(rtmsg.dst);
1226 rtmsg.dst.sin_family = AF_INET;
1227 rtmsg.gway.sin_len = sizeof(rtmsg.gway);
1228 rtmsg.gway.sin_family = AF_INET;
1229 rtmsg.gway.sin_addr.s_addr = g;
1230 rtmsg.mask.sin_len = sizeof(rtmsg.dst);
1231 rtmsg.mask.sin_family = AF_INET;
1232
1233 rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
1234 if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
1235 syslog(LOG_ERR, "Couldn't %s default route: %d",
1236 cmd=='s'? "add": "delete",errno);
1237 close(routes);
1238 return 0;
1239 }
1240
1241 close(routes);
1242 default_route_gateway = (cmd == 's')? g: 0;
1243 return 1;
1244 }
1245
1246 //==========================================================================
1247
1248 #if RTM_VERSION >= 3
1249
1250 /*
1251 * sifproxyarp - Make a proxy ARP entry for the peer.
1252 */
1253 static struct {
1254 struct rt_msghdr hdr;
1255 struct sockaddr_inarp dst;
1256 struct sockaddr_dl hwa;
1257 char extra[128];
1258 } arpmsg;
1259
1260 static int arpmsg_valid;
1261
1262 int
sifproxyarp(unit,hisaddr)1263 sifproxyarp(unit, hisaddr)
1264 int unit;
1265 u_int32_t hisaddr;
1266 {
1267 int routes;
1268
1269 db_printf("%s called\n", __PRETTY_FUNCTION__);
1270 /*
1271 * Get the hardware address of an interface on the same subnet
1272 * as our local address.
1273 */
1274 memset(&arpmsg, 0, sizeof(arpmsg));
1275 if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
1276 syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1277 return 0;
1278 }
1279
1280 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1281 syslog(LOG_ERR, "Couldn't add proxy arp entry: socket: %m");
1282 return 0;
1283 }
1284
1285 arpmsg.hdr.rtm_type = RTM_ADD;
1286 arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
1287 arpmsg.hdr.rtm_version = RTM_VERSION;
1288 arpmsg.hdr.rtm_seq = ++rtm_seq;
1289 arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
1290 arpmsg.hdr.rtm_inits = RTV_EXPIRE;
1291 arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
1292 arpmsg.dst.sin_family = AF_INET;
1293 arpmsg.dst.sin_addr.s_addr = hisaddr;
1294 arpmsg.dst.sin_other = SIN_PROXY;
1295
1296 arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
1297 + arpmsg.hwa.sdl_len;
1298 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1299 syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
1300 close(routes);
1301 return 0;
1302 }
1303
1304 close(routes);
1305 arpmsg_valid = 1;
1306 proxy_arp_addr = hisaddr;
1307 return 1;
1308 }
1309
1310 /*
1311 * cifproxyarp - Delete the proxy ARP entry for the peer.
1312 */
1313 int
cifproxyarp(unit,hisaddr)1314 cifproxyarp(unit, hisaddr)
1315 int unit;
1316 u_int32_t hisaddr;
1317 {
1318 int routes;
1319
1320 db_printf("%s called\n", __PRETTY_FUNCTION__);
1321 if (!arpmsg_valid)
1322 return 0;
1323 arpmsg_valid = 0;
1324
1325 arpmsg.hdr.rtm_type = RTM_DELETE;
1326 arpmsg.hdr.rtm_seq = ++rtm_seq;
1327
1328 if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
1329 syslog(LOG_ERR, "Couldn't delete proxy arp entry: socket: %m");
1330 return 0;
1331 }
1332
1333 if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
1334 syslog(LOG_ERR, "Couldn't delete proxy arp entry: %m");
1335 close(routes);
1336 return 0;
1337 }
1338
1339 close(routes);
1340 proxy_arp_addr = 0;
1341 return 1;
1342 }
1343
1344 //==========================================================================
1345
1346 #else /* RTM_VERSION */
1347
1348 /*
1349 * sifproxyarp - Make a proxy ARP entry for the peer.
1350 */
1351 int
sifproxyarp(unit,hisaddr)1352 sifproxyarp(unit, hisaddr)
1353 int unit;
1354 u_int32_t hisaddr;
1355 {
1356 struct arpreq arpreq;
1357 struct {
1358 struct sockaddr_dl sdl;
1359 char space[128];
1360 } dls;
1361
1362 db_printf("%s called\n", __PRETTY_FUNCTION__);
1363 BZERO(&arpreq, sizeof(arpreq));
1364
1365 /*
1366 * Get the hardware address of an interface on the same subnet
1367 * as our local address.
1368 */
1369 if (!get_ether_addr(hisaddr, &dls.sdl)) {
1370 syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1371 return 0;
1372 }
1373
1374 arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
1375 arpreq.arp_ha.sa_family = AF_UNSPEC;
1376 BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
1377 SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1378 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1379 arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1380 if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
1381 syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
1382 return 0;
1383 }
1384
1385 proxy_arp_addr = hisaddr;
1386 return 1;
1387 }
1388
1389 /*
1390 * cifproxyarp - Delete the proxy ARP entry for the peer.
1391 */
1392 int
cifproxyarp(unit,hisaddr)1393 cifproxyarp(unit, hisaddr)
1394 int unit;
1395 u_int32_t hisaddr;
1396 {
1397 struct arpreq arpreq;
1398
1399 db_printf("%s called\n", __PRETTY_FUNCTION__);
1400 BZERO(&arpreq, sizeof(arpreq));
1401 SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1402 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
1403 if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
1404 syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m");
1405 return 0;
1406 }
1407 proxy_arp_addr = 0;
1408 return 1;
1409 }
1410 #endif /* RTM_VERSION */
1411
1412
1413 //==========================================================================
1414 /*
1415 * get_ether_addr - get the hardware address of an interface on the
1416 * the same subnet as ipaddr.
1417 */
1418 #define MAX_IFS 32
1419
1420 static int
get_ether_addr(ipaddr,hwaddr)1421 get_ether_addr(ipaddr, hwaddr)
1422 u_int32_t ipaddr;
1423 struct sockaddr_dl *hwaddr;
1424 {
1425 struct ifreq *ifr, *ifend, *ifp;
1426 u_int32_t ina, mask;
1427 struct sockaddr_dl *dla;
1428 struct ifreq ifreq;
1429 struct ifconf ifc;
1430 struct ifreq ifs[MAX_IFS];
1431
1432 db_printf("%s called\n", __PRETTY_FUNCTION__);
1433 ifc.ifc_len = sizeof(ifs);
1434 ifc.ifc_req = ifs;
1435 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1436 syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1437 return 0;
1438 }
1439
1440 /*
1441 * Scan through looking for an interface with an Internet
1442 * address on the same subnet as `ipaddr'.
1443 */
1444 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1445 for (ifr = ifc.ifc_req; ifr < ifend;
1446 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
1447 + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
1448 if (ifr->ifr_addr.sa_family == AF_INET) {
1449 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1450 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1451 /*
1452 * Check that the interface is up, and not point-to-point
1453 * or loopback.
1454 */
1455 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1456 continue;
1457 if ((ifreq.ifr_flags &
1458 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
1459 != (IFF_UP|IFF_BROADCAST))
1460 continue;
1461 /*
1462 * Get its netmask and check that it's on the right subnet.
1463 */
1464 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1465 continue;
1466 mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1467 if ((ipaddr & mask) != (ina & mask))
1468 continue;
1469
1470 break;
1471 }
1472 }
1473
1474 if (ifr >= ifend)
1475 return 0;
1476 syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
1477
1478 /*
1479 * Now scan through again looking for a link-level address
1480 * for this interface.
1481 */
1482 ifp = ifr;
1483 for (ifr = ifc.ifc_req; ifr < ifend; ) {
1484 if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
1485 && ifr->ifr_addr.sa_family == AF_LINK) {
1486 /*
1487 * Found the link-level address - copy it out
1488 */
1489 dla = (struct sockaddr_dl *) &ifr->ifr_addr;
1490 BCOPY(dla, hwaddr, dla->sdl_len);
1491 return 1;
1492 }
1493 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
1494 + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)));
1495 }
1496
1497 return 0;
1498 }
1499
1500 //==========================================================================
1501 /*
1502 * Return user specified netmask, modified by any mask we might determine
1503 * for address `addr' (in network byte order).
1504 * Here we scan through the system's list of interfaces, looking for
1505 * any non-point-to-point interfaces which might appear to be on the same
1506 * network as `addr'. If we find any, we OR in their netmask to the
1507 * user-specified netmask.
1508 */
1509 u_int32_t
GetMask(addr)1510 GetMask(addr)
1511 u_int32_t addr;
1512 {
1513 u_int32_t mask, nmask, ina;
1514 struct ifreq *ifr, *ifend, ifreq;
1515 struct ifconf ifc;
1516 struct ifreq ifs[MAX_IFS];
1517
1518 addr = ntohl(addr);
1519 if (IN_CLASSA(addr)) /* determine network mask for address class */
1520 nmask = IN_CLASSA_NET;
1521 else if (IN_CLASSB(addr))
1522 nmask = IN_CLASSB_NET;
1523 else
1524 nmask = IN_CLASSC_NET;
1525 /* class D nets are disallowed by bad_ip_adrs */
1526 mask = netmask | htonl(nmask);
1527
1528 /*
1529 * Scan through the system's network interfaces.
1530 */
1531 ifc.ifc_len = sizeof(ifs);
1532 ifc.ifc_req = ifs;
1533 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
1534 syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1535 return mask;
1536 }
1537 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1538 for (ifr = ifc.ifc_req; ifr < ifend;
1539 ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
1540 + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
1541 /*
1542 * Check the interface's internet address.
1543 */
1544 if (ifr->ifr_addr.sa_family != AF_INET)
1545 continue;
1546 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1547 if ((ntohl(ina) & nmask) != (addr & nmask))
1548 continue;
1549 /*
1550 * Check that the interface is up, and not point-to-point or loopback.
1551 */
1552 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1553 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1554 continue;
1555 if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
1556 != IFF_UP)
1557 continue;
1558 /*
1559 * Get its netmask and OR it into our mask.
1560 */
1561 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1562 continue;
1563 mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1564 }
1565
1566 return mask;
1567 }
1568
1569 //==========================================================================
1570 /*
1571 * Use the hostid as part of the random number seed.
1572 */
1573 int
get_host_seed()1574 get_host_seed()
1575 {
1576 //db_printf("%s called\n", __PRETTY_FUNCTION__);
1577 #ifndef __ECOS
1578 return gethostid();
1579 #endif
1580 return 0;
1581 }
1582
1583 //=====================================================================
1584 // PAP stubs
1585 //
1586 // When omitting PAP, these fill in the dangling references from auth.c
1587 //
1588
1589 #ifndef CYGPKG_PPP_PAP
1590
1591 void
upap_authwithpeer(unit,user,password)1592 upap_authwithpeer(unit, user, password)
1593 int unit;
1594 char *user, *password;
1595 {
1596 unit=unit;
1597 user=user;
1598 password=password;
1599 }
1600
1601 void
upap_authpeer(unit)1602 upap_authpeer(unit)
1603 int unit;
1604 {
1605 unit=unit;
1606 }
1607
1608 #endif
1609
1610 //=====================================================================
1611 // CHAP stubs
1612 //
1613 // When omitting CHAP, these fill in the dangling references from auth.c
1614 //
1615
1616 #ifndef CYGPKG_PPP_CHAP
1617
1618 void
ChapAuthWithPeer(unit,our_name,digest)1619 ChapAuthWithPeer(unit, our_name, digest)
1620 int unit;
1621 char *our_name;
1622 int digest;
1623 {
1624 unit=unit;
1625 our_name=our_name;
1626 digest=digest;
1627 }
1628
1629 void
ChapAuthPeer(unit,our_name,digest)1630 ChapAuthPeer(unit, our_name, digest)
1631 int unit;
1632 char *our_name;
1633 int digest;
1634 {
1635 unit=unit;
1636 our_name=our_name;
1637 digest=digest;
1638 }
1639
1640 #endif
1641
1642 //=====================================================================
1643 // eCos API
1644
cyg_ppp_options_init(cyg_ppp_options_t * options)1645 externC cyg_int32 cyg_ppp_options_init( cyg_ppp_options_t *options )
1646 {
1647 if( options == NULL )
1648 return -1;
1649
1650 options->debug = 0;
1651 options->kdebugflag = 0;
1652 options->default_route = 1;
1653 options->modem = 0;
1654 options->flowctl = CYG_PPP_FLOWCTL_HARDWARE;
1655 options->refuse_pap = 0;
1656 options->refuse_chap = 0;
1657 options->neg_accm = 0;
1658 options->conf_accm = 0;
1659
1660 options->baud = CYGNUM_SERIAL_BAUD_115200;
1661
1662 options->idle_time_limit = 1*60;
1663 options->maxconnect = 0;
1664
1665 options->our_address = 0;
1666 options->his_address = 0;
1667
1668 options->script = NULL;
1669
1670 strncpy( options->user, CYGPKG_PPP_AUTH_DEFAULT_USER, MAXNAMELEN );
1671 strncpy( options->passwd, CYGPKG_PPP_AUTH_DEFAULT_PASSWD, MAXSECRETLEN );
1672
1673 return 0;
1674 }
1675
1676 // -------------------------------------------------------------------------
1677
1678
1679 #define CYGNUM_PPP_PPPD_THREAD_STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL+0x1000)
1680
1681 static char cyg_pppd_stack[CYGNUM_PPP_PPPD_THREAD_STACK_SIZE];
1682 static cyg_thread cyg_pppd_thread_obj;
1683
1684 static char cyg_ppp_tx_thread_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
1685 static cyg_thread cyg_ppp_tx_thread_obj;
1686
1687
1688 externC void cyg_pppd_main(CYG_ADDRWORD arg);
1689
1690
cyg_ppp_up(const char * devnam_arg,const cyg_ppp_options_t * options)1691 externC cyg_ppp_handle_t cyg_ppp_up( const char *devnam_arg,
1692 const cyg_ppp_options_t *options )
1693 {
1694
1695 if( options == NULL || phase != PHASE_DEAD )
1696 return 0;
1697
1698 // Initialize control block
1699 memset(&ppp_tty, 0, sizeof(struct tty));
1700
1701 strncpy( devnam, devnam_arg, PATH_MAX );
1702
1703 ppp_tty.options = options;
1704
1705 // Start the PPPD thread
1706 cyg_thread_create(CYGNUM_PPP_PPPD_THREAD_PRIORITY,
1707 cyg_pppd_main,
1708 (CYG_ADDRWORD)&ppp_tty,
1709 "PPPD",
1710 &cyg_pppd_stack[0],
1711 CYGNUM_PPP_PPPD_THREAD_STACK_SIZE,
1712 &ppp_tty.pppd_thread,
1713 &cyg_pppd_thread_obj
1714 );
1715 cyg_thread_resume(ppp_tty.pppd_thread);
1716
1717 // Start the TX thread
1718 cyg_semaphore_init( &ppp_tty.tx_sem, 0 );
1719
1720 cyg_thread_create(CYGNUM_PPP_PPPD_THREAD_PRIORITY+1,
1721 cyg_ppp_tx_thread,
1722 (CYG_ADDRWORD)&ppp_tty,
1723 "PPP Tx Thread",
1724 &cyg_ppp_tx_thread_stack[0],
1725 sizeof(cyg_ppp_tx_thread_stack),
1726 &ppp_tty.tx_thread,
1727 &cyg_ppp_tx_thread_obj
1728 );
1729 cyg_thread_resume(ppp_tty.tx_thread);
1730
1731 // Wait for the PPPD thread to get going and start the PPP
1732 // initialization phase.
1733 while(phase == PHASE_DEAD )
1734 cyg_thread_delay(100);
1735
1736 return (cyg_ppp_handle_t)&ppp_tty;
1737 }
1738
1739 // -------------------------------------------------------------------------
1740
1741 externC char **script;
1742
cyg_ppp_options_install(const cyg_ppp_options_t * options)1743 externC void cyg_ppp_options_install( const cyg_ppp_options_t *options )
1744 {
1745 debug = options->debug;
1746 kdebugflag = options->kdebugflag;
1747
1748 modem = options->modem;
1749 flowctl = options->flowctl;
1750 refuse_pap = options->refuse_pap;
1751 refuse_chap = options->refuse_chap;
1752 neg_accm = options->neg_accm;
1753 conf_accm = options->conf_accm;
1754
1755 inspeed = options->baud;
1756
1757 idle_time_limit = options->idle_time_limit;
1758 maxconnect = options->maxconnect;
1759
1760 script = options->script;
1761
1762 strncpy( user, &options->user[0], MAXNAMELEN );
1763 strncpy( passwd, &options->passwd[0], MAXSECRETLEN );
1764
1765 }
1766
1767 // -------------------------------------------------------------------------
1768
cyg_ppp_down(const cyg_ppp_handle_t handle)1769 externC cyg_int32 cyg_ppp_down( const cyg_ppp_handle_t handle )
1770 {
1771 if( phase != PHASE_DEAD )
1772 {
1773 externC int kill_link;
1774 kill_link = 1;
1775 cyg_thread_release( ppp_tty.pppd_thread );
1776 ppp_tty.pppd_wakeup = 1;
1777 return 0;
1778 }
1779 else
1780 return -1;
1781 }
1782
1783 // -------------------------------------------------------------------------
1784
cyg_ppp_wait_up(cyg_ppp_handle_t handle)1785 externC cyg_int32 cyg_ppp_wait_up( cyg_ppp_handle_t handle )
1786 {
1787 while(!( (phase == PHASE_NETWORK && ifaddrs[0] != 0) ||
1788 phase == PHASE_DEAD ) )
1789 cyg_thread_delay(100);
1790
1791 return phase == PHASE_NETWORK ? 0 : -1;
1792 }
1793
1794 // -------------------------------------------------------------------------
1795
cyg_ppp_wait_down(cyg_ppp_handle_t handle)1796 externC void cyg_ppp_wait_down( cyg_ppp_handle_t handle )
1797 {
1798 while( ppp_tty.tx_thread_running || ppp_tty.pppd_thread_running )
1799 cyg_thread_delay(100);
1800
1801 cyg_thread_delete( ppp_tty.tx_thread );
1802 cyg_thread_delete( ppp_tty.pppd_thread );
1803 }
1804
1805 // -------------------------------------------------------------------------
1806 #ifdef CYGOPT_PPP_NS_NEGOTIATE
cyg_ppp_get_neg_addrs(cyg_ppp_neg_addrs_t * addrs)1807 externC u_int32_t cyg_ppp_get_neg_addrs(cyg_ppp_neg_addrs_t *addrs)
1808 {
1809 if (phase == PHASE_NETWORK && ifaddrs[0] != 0)
1810 {
1811 addrs->local_ip = ipcp_gotoptions[0].ouraddr;
1812 addrs->peer_ip = ipcp_hisoptions[0].hisaddr;
1813 addrs->pri_dns = ipcp_gotoptions[0].dnsaddr[0];
1814 addrs->alt_dns = ipcp_gotoptions[0].dnsaddr[1];
1815 addrs->pri_wins = ipcp_gotoptions[0].winsaddr[0];
1816 addrs->alt_wins = ipcp_gotoptions[0].winsaddr[1];
1817 return(1);
1818 }
1819 else
1820 {
1821 return(0);
1822 }
1823 }
1824 #endif
1825 //=====================================================================
1826 // eCos extras
1827
syslog(int level,char * fmt,...)1828 void syslog( int level, char *fmt, ... )
1829 {
1830 va_list ap;
1831 int ret;
1832
1833 #ifdef CYGPKG_PPP_DEBUG_WARN_ONLY
1834 if(!( level == LOG_ERR ||
1835 level == LOG_WARNING ))
1836 return;
1837 #endif
1838
1839 va_start(ap, fmt);
1840 diag_printf("SYSLOG %02x: ",level);
1841 ret = diag_vprintf(fmt, ap);
1842 diag_printf("\n");
1843 va_end(ap);
1844 }
1845
1846 //=====================================================================
1847
crypt(const char * key,const char * salt)1848 char *crypt (const char *key, const char *salt)
1849 {
1850 static char res[13];
1851
1852 db_printf("%s called\n", __PRETTY_FUNCTION__);
1853
1854 return res;
1855 }
1856
1857
1858 //=====================================================================
1859 /*
1860 * Substitute procedures for those systems which don't have
1861 * drand48 et al.
1862 */
1863
1864 double
drand48(void)1865 drand48(void)
1866 {
1867 return (double)rand() / (double)0x7fffffffL; /* 2**31-1 */
1868 }
1869
1870 long
mrand48(void)1871 mrand48(void)
1872 {
1873 return rand();
1874 }
1875
1876 void
srand48(long seedval)1877 srand48(long seedval)
1878 {
1879 srand(seedval);
1880 }
1881
1882
1883 //=====================================================================
1884
1885 #if 0
1886
1887 #undef MD5Init
1888 #undef MD5Update
1889 #undef MD5Final
1890
1891 #include <sys/types.h>
1892
1893 #include <sys/md5.h>
1894
1895
1896 void cyg_MD5Init( MD5_CTX *ctx );
1897 void cyg_MD5Update (MD5_CTX *ctx, const unsigned char *buf, unsigned int size);
1898 void cyg_MD5Final (unsigned char hash[16], MD5_CTX *ctx);
1899
1900
1901 void cyg_ppp_MD5Init( MD5_CTX *ctx )
1902 {
1903 db_printf("%s called\n", __PRETTY_FUNCTION__);
1904 cyg_MD5Init( ctx );
1905 return;
1906 }
1907
1908 void cyg_ppp_MD5Update (MD5_CTX *ctx, const unsigned char *buf, unsigned int size)
1909 {
1910 db_printf("%s called\n", __PRETTY_FUNCTION__);
1911 cyg_MD5Update( ctx, buf, size );
1912 return;
1913 }
1914
1915 void cyg_ppp_MD5Final (unsigned char hash[16], MD5_CTX *ctx)
1916 {
1917 db_printf("%s called\n", __PRETTY_FUNCTION__);
1918 cyg_MD5Final( hash, ctx );
1919 return;
1920 }
1921
1922 #endif
1923
1924 //=====================================================================
1925 // End of sys-ecos.c
1926
1927
1928