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