ppp_vxworks.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:18k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* ppp_vxworks.c - System-dependent procedures for setting up PPP interfaces */
  2. /* Copyright 1995 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1989 Carnegie Mellon University.
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by Carnegie Mellon University.  The name of the
  14.  * University may not be used to endorse or promote products derived
  15.  * from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20. /*
  21. modification history
  22. --------------------
  23. 01i,30jan01,ijm  Fixed spr 34274, OPT_PROXYARP is not setting ARP entry
  24.  correctly.  It times out.
  25. 01h,17feb99,sgv  Fixed spr 22486, Proxy Arp fix.
  26. 01g,05aug96,vin  upgraded to BSD4.4., replaced rtentry with ortentry,
  27.  reworked get_ether_addr since ifreq struct changed.
  28.  switched the order of initialization in sifaddr(). 
  29. 01f,16jun95,dzb  header file consolidation.
  30. 01e,15may95,dzb  changed LOG_ERR for route delete to LOG_WARNING.
  31. 01d,06mar95,dzb  proxyArp fix (SPR #4074).
  32. 01c,07feb95,dzb  changed to look for OK from pppwrite().
  33. 01b,16jan95,dzb  renamed to ppp_vxworks.c. warnings cleanup.
  34. 01a,21dec94,dab  VxWorks port - first WRS version.
  35.    +dzb  added: path for ppp header files, WRS copyright.
  36. */
  37. #include "vxWorks.h"
  38. #include "string.h"
  39. #include "stdlib.h"
  40. #include "stdio.h"
  41. #include "ioctl.h"
  42. #include "ioLib.h"
  43. #include "sys/ioctl.h"
  44. #include "sys/types.h"
  45. #include "sys/socket.h"
  46. #include "sys/times.h"
  47. #include "net/if.h"
  48. #include "net/if_arp.h"
  49. #include "netinet/if_ether.h"
  50. #include "net/if_dl.h"
  51. #include "errno.h"
  52. #include "net/if.h"
  53. #include "net/route.h"
  54. #include "netinet/in.h"
  55. #include "pppLib.h"
  56. #include "logLib.h"
  57. IMPORT struct ifnet     *ifnet;         /* list of all network interfaces */
  58. IMPORT void arptfree (struct llinfo_arp *);
  59.  
  60. int pppArpCmd (int cmd, struct arpreq * ar);
  61. /*
  62.  * establish_ppp - Turn the serial port into a ppp interface.
  63.  */
  64. void
  65. establish_ppp()
  66. {
  67.     int x;
  68.     /* get ppp fd */
  69.     if (ppptioctl(ppp_unit, PPPIOCGFD, (caddr_t) &(ppp_if[ppp_unit]->fd)) < 0) {
  70.         syslog(LOG_ERR, "ppptioctl(PPPIOCGFD) error");
  71.         die(ppp_unit, 1);
  72.     }
  73.     /*
  74.      * Enable debug in the driver if requested.
  75.      */
  76.     if (ppp_if[ppp_unit]->kdebugflag) {
  77.         if (ppptioctl(ppp_unit, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
  78.             syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): error");
  79.         } else {
  80.             x |= (ppp_if[ppp_unit]->kdebugflag & 0xFF) * SC_DEBUG;
  81.             if (ppptioctl(ppp_unit, PPPIOCSFLAGS, (caddr_t) &x) < 0)
  82.                 syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): error");
  83.         }
  84.     }
  85. }
  86. /*
  87.  * disestablish_ppp - Restore the serial port to normal operation.
  88.  * This shouldn't call die() because it's called from die().
  89.  */
  90. void
  91. disestablish_ppp()
  92. {
  93. }
  94. /*
  95.  * output - Output PPP packet.
  96.  */
  97. void
  98. output(unit, p, len)
  99.     int unit;
  100.     u_char *p;
  101.     int len;
  102. {
  103.     if (ppp_if[unit]->debug)
  104.         log_packet(p, len, "sent ");
  105.     if (pppwrite(unit, (char *) p, len) != OK) {
  106. syslog(LOG_ERR, "write error");
  107. die(unit, 1);
  108.     }
  109. }
  110. /*
  111.  * read_packet - get a PPP packet from the serial device.
  112.  */
  113. int
  114. read_packet(buf)
  115.     u_char *buf;
  116. {
  117.     int len;
  118.     len = pppread(ppp_unit, (char *) buf, MTU + DLLHEADERLEN);
  119.     if (len == 0) {
  120.         MAINDEBUG((LOG_DEBUG, "read(fd): EWOULDBLOCK"));
  121. return -1;
  122.     }
  123.     return len;
  124. }
  125. /*
  126.  * ppp_send_config - configure the transmit characteristics of
  127.  * the ppp interface.
  128.  */
  129. void
  130. ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
  131.     int unit, mtu;
  132.     u_long asyncmap;
  133.     int pcomp, accomp;
  134. {
  135.     u_int x;
  136.     if (ppptioctl(unit, SIOCSIFMTU, (caddr_t) &mtu) < 0) {
  137. syslog(LOG_ERR, "ioctl(SIOCSIFMTU) error");
  138. die(unit, 1);
  139.     }
  140.     if (ppptioctl(unit, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
  141. syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP) error");
  142. die(unit, 1);
  143.     }
  144.     if (ppptioctl(unit, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
  145. syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS) error");
  146. die(unit, 1);
  147.     }
  148.     x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
  149.     x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
  150.     if (ppptioctl(unit, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
  151. syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS) error");
  152. die(unit, 1);
  153.     }
  154. }
  155. /*
  156.  * ppp_set_xaccm - set the extended transmit ACCM for the interface.
  157.  */
  158. void
  159. ppp_set_xaccm(unit, accm)
  160.     int unit;
  161.     ext_accm accm;
  162. {
  163.     if (ppptioctl(unit, PPPIOCSXASYNCMAP, (caddr_t) accm) < 0)
  164.         syslog(LOG_WARNING, "ioctl(set extended ACCM): error");
  165. }
  166. /*
  167.  * ppp_recv_config - configure the receive-side characteristics of
  168.  * the ppp interface.
  169.  */
  170. void
  171. ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
  172.     int unit, mru;
  173.     u_long asyncmap;
  174.     int pcomp, accomp;
  175. {
  176.     int x;
  177.     if (ppptioctl(unit, PPPIOCSMRU, (caddr_t) &mru) < 0) {
  178.         syslog(LOG_ERR, "ioctl(PPPIOCSMRU): error");
  179. die(unit, 1);
  180.     }
  181.     if (ppptioctl(unit, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
  182.         syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): error");
  183. die(unit, 1);
  184.     }
  185.     if (ppptioctl(unit, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
  186.         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): error");
  187. die(unit, 1);
  188.     }
  189.     x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
  190.     if (ppptioctl(unit, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
  191.         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): error");
  192. die(unit, 1);
  193.     }
  194. }
  195. /*
  196.  * sifvjcomp - config tcp header compression
  197.  */
  198. int
  199. sifvjcomp(u, vjcomp, cidcomp, maxcid)
  200.     int u, vjcomp, cidcomp, maxcid;
  201. {
  202.     u_int x;
  203.     if (ppptioctl(u, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
  204. syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS) error");
  205. return 0;
  206.     }
  207.     x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
  208.     x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
  209.     if (ppptioctl(u, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
  210. syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS) error");
  211. return 0;
  212.     }
  213.     if (ppptioctl(u, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
  214.         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): error");
  215.         return 0;
  216.     }
  217.     return 1;
  218. }
  219. /*
  220.  * sifup - Config the interface up and enable IP packets to pass.
  221.  */
  222. int
  223. sifup(u)
  224.     int u;
  225. {
  226.     struct ifreq ifr;
  227.     u_int x;
  228.     strncpy(ifr.ifr_name, ppp_if[u]->ifname, sizeof (ifr.ifr_name));
  229.     if (ioctl(ppp_if[u]->s, SIOCGIFFLAGS, (int) &ifr) < 0) {
  230. syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS) error");
  231. return 0;
  232.     }
  233.     ifr.ifr_flags |= IFF_UP;
  234.     if (ioctl(ppp_if[u]->s, SIOCSIFFLAGS, (int) &ifr) < 0) {
  235. syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS) error");
  236. return 0;
  237.     }
  238.     if (ppptioctl(u, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
  239.         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): error");
  240.         return 0;
  241.     }
  242.     x |= SC_ENABLE_IP;
  243.     if (ppptioctl(u, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
  244.         syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): error");
  245.         return 0;
  246.     }
  247.     return 1;
  248. }
  249. /*
  250.  * sifdown - Config the interface down and disable IP.
  251.  */
  252. int
  253. sifdown(u)
  254.     int u;
  255. {
  256.     struct ifreq ifr;
  257.     u_int x;
  258.     int rv;
  259.     rv = 1;
  260.     if (ppptioctl(u, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
  261.         syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): error");
  262.         rv = 0;
  263.     } else {
  264.         x &= ~SC_ENABLE_IP;
  265.         if (ppptioctl(u, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
  266.             syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): error");
  267.             rv = 0;
  268.         }
  269.     }
  270.     strncpy(ifr.ifr_name, ppp_if[u]->ifname, sizeof (ifr.ifr_name));
  271.     if (ioctl(ppp_if[u]->s, SIOCGIFFLAGS, (int) &ifr) < 0) {
  272. syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS) error");
  273. rv = 0;
  274.     } else {
  275.         ifr.ifr_flags &= ~IFF_UP;
  276.         if (ioctl(ppp_if[u]->s, SIOCSIFFLAGS, (int) &ifr) < 0) {
  277.     syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): error");
  278.     rv = 0;
  279.         }
  280.     }
  281.     return rv;
  282. }
  283. /*
  284.  * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
  285.  * if it exists.
  286.  */
  287. #define SET_SA_FAMILY(addr, family)
  288.     BZERO((char *) &(addr), sizeof(addr));
  289.     addr.sa_family = (family);
  290. /*
  291.  * sifaddr - Config the interface IP addresses and netmask.
  292.  */
  293. int
  294. sifaddr(u, o, h, m)
  295.     int u, o, h, m;
  296. {
  297.     struct ifreq ifr;
  298.     strncpy(ifr.ifr_name, ppp_if[u]->ifname, sizeof(ifr.ifr_name));
  299.     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
  300.     ifr.ifr_addr.sa_len = sizeof (struct sockaddr_in);
  301.     if (m != 0) {
  302.         ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
  303.         syslog(LOG_NOTICE, "Setting interface mask to %s", ip_ntoa(m));
  304.         if (ioctl(ppp_if[u]->s, SIOCSIFNETMASK, (int) &ifr) < 0) {
  305.     syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): error");
  306.     return (0); 
  307. }
  308.     }
  309.     SET_SA_FAMILY(ifr.ifr_dstaddr, AF_INET);
  310.     ifr.ifr_dstaddr.sa_len = sizeof (struct sockaddr_in);
  311.     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
  312.     if (ioctl(ppp_if[u]->s, SIOCSIFDSTADDR, (int) &ifr) < 0) {
  313.         syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): error");
  314. return (0); 
  315.     }
  316.     SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
  317.     ifr.ifr_addr.sa_len = sizeof (struct sockaddr_in);
  318.     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
  319.     if (ioctl(ppp_if[u]->s, SIOCSIFADDR, (int) &ifr) < 0) {
  320.         syslog(LOG_ERR, "ioctl(SIOCSIFADDR): error");
  321. return (0); 
  322.     }
  323.     return 1;
  324. }
  325. /*
  326.  * cifaddr - Clear the interface IP addresses, and delete routes
  327.  * through the interface if possible.
  328.  */
  329. int
  330. cifaddr(u, o, h)
  331.     int u, o, h;
  332. {
  333.     struct ortentry rt;
  334.     
  335.     SET_SA_FAMILY(rt.rt_dst, AF_INET);
  336.     rt.rt_dst.sa_len = sizeof (struct sockaddr_in);
  337.     ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
  338.     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
  339.     rt.rt_gateway.sa_len = sizeof (struct sockaddr_in);
  340.     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
  341.     rt.rt_flags = RTF_HOST;
  342.     if (ioctl(ppp_if[u]->s, SIOCDELRT, (int) &rt) < 0) {
  343.         syslog(LOG_WARNING, "ioctl(SIOCDELRT) error");
  344.         return 0;
  345.     }
  346.     return 1;
  347. }
  348. /*
  349.  * sifdefaultroute - assign a default route through the address given.
  350.  */
  351. int
  352. sifdefaultroute(u, g)
  353.     int u, g;
  354. {
  355.     struct ortentry rt;
  356.     SET_SA_FAMILY(rt.rt_dst, AF_INET);
  357.     rt.rt_dst.sa_len = sizeof (struct sockaddr_in);
  358.     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
  359.     rt.rt_gateway.sa_len = sizeof (struct sockaddr_in);
  360.     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
  361.     rt.rt_flags = RTF_GATEWAY;
  362.     if (ioctl(ppp_if[u]->s, SIOCADDRT, (int) &rt) < 0) {
  363.         syslog(LOG_ERR, "default route ioctl(SIOCADDRT): error");
  364.         return 0;
  365.     }
  366.     return 1;
  367. }
  368. /*
  369.  * cifdefaultroute - delete a default route through the address given.
  370.  */
  371. int
  372. cifdefaultroute(u, g)
  373.     int u, g;
  374. {
  375.     struct ortentry rt;
  376.     SET_SA_FAMILY(rt.rt_dst, AF_INET);
  377.     rt.rt_dst.sa_len = sizeof (struct sockaddr_in);
  378.     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
  379.     rt.rt_gateway.sa_len = sizeof (struct sockaddr_in);
  380.     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
  381.     rt.rt_flags = RTF_GATEWAY;
  382.     if (ioctl(ppp_if[u]->s, SIOCDELRT, (int) &rt) < 0)
  383.         syslog(LOG_WARNING, "default route ioctl(SIOCDELRT): error");
  384.     return 1;
  385. }
  386. /*
  387.  * sifproxyarp - Make a proxy ARP entry for the peer.
  388.  */
  389. int
  390. sifproxyarp(unit, hisaddr)
  391.     int unit;
  392.     u_long hisaddr;
  393. {
  394.     struct arpreq arpreq;
  395.     BZERO((char *)&arpreq, sizeof(arpreq));
  396.     /*
  397.      * Get the hardware address of an interface on the same subnet
  398.      * as our local address.
  399.      */
  400.     if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
  401. syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
  402. return 0;
  403.     }
  404.     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
  405.     arpreq.arp_pa.sa_len = sizeof (struct sockaddr_in);
  406.    ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
  407.     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
  408.     pppArpCmd (SIOCSARP, &arpreq);
  409.     return 1;
  410. }
  411. int pppArpCmd
  412.    (
  413.    int cmd, 
  414.    struct arpreq * ar
  415.    )
  416.    {
  417.    struct sockaddr_in *       soInAddr;
  418.    struct llinfo_arp *        la = NULL;
  419.    struct rtentry *           rt = NULL;
  420.    struct sockaddr_dl *       sdl= NULL;
  421.    if (ar->arp_pa.sa_family != AF_INET ||
  422.        ar->arp_ha.sa_family != AF_UNSPEC)
  423.        return (EAFNOSUPPORT);
  424.    soInAddr = (struct sockaddr_in *)&ar->arp_pa;
  425.    switch (cmd)
  426.         {
  427.         case SIOCSARP:
  428.             {
  429.     register struct rtentry *rt;
  430.             static struct sockaddr_inarp sin = {sizeof(sin), AF_INET };
  431.     int proxy = 1;
  432.     int create = 1;
  433. #define rt_expire rt_rmx.rmx_expire
  434. #define SDL(s) ((struct sockaddr_dl *)s)
  435.             sin.sin_addr.s_addr = soInAddr->sin_addr.s_addr;
  436.             sin.sin_other = proxy ? SIN_PROXY : 0;
  437.             rt = rtalloc1((struct sockaddr *)&sin, create);
  438.             if (rt == 0)
  439.                 return (0);
  440.             rt->rt_refcnt--;
  441.     rt->rt_expire = 0;
  442.             if ((rt->rt_flags & RTF_GATEWAY) || 
  443.                 (rt->rt_flags & RTF_LLINFO) == 0 ||
  444.                  rt->rt_gateway->sa_family != AF_LINK) {
  445.                  if (create)
  446.                         logMsg("arptnew failed on %xn", 
  447. (int)ntohl(soInAddr->sin_addr.s_addr),
  448.                         0,0,0,0,0);
  449.                  return (0);
  450.             }
  451.             la = (struct llinfo_arp *)rt->rt_llinfo;
  452.             }
  453.             rt = la->la_rt;
  454.             sdl = SDL(rt->rt_gateway);
  455.             bcopy((caddr_t)ar->arp_ha.sa_data, LLADDR(sdl),
  456.                   sdl->sdl_alen = sizeof(struct ether_addr));
  457.             rt->rt_flags &= ~RTF_REJECT;
  458.             rt->rt_flags |= RTF_STATIC; /* manually added route. */
  459.             la->la_asked = 0;
  460.             break;
  461.         case SIOCDARP:          /* delete entry */
  462.             {
  463.     register struct rtentry *rt;
  464.             static struct sockaddr_inarp sin = {sizeof(sin), AF_INET };
  465.     int proxy = 1;
  466.     int create = 0;
  467.             sin.sin_addr.s_addr = soInAddr->sin_addr.s_addr;
  468.             sin.sin_other = proxy ? SIN_PROXY : 0;
  469.             rt = rtalloc1((struct sockaddr *)&sin, create);
  470.             if (rt == 0)
  471.                 return (0);
  472.             rt->rt_refcnt--;
  473.             if ((rt->rt_flags & RTF_GATEWAY) || 
  474.                 (rt->rt_flags & RTF_LLINFO) == 0 ||
  475.                  rt->rt_gateway->sa_family != AF_LINK) {
  476.                  if (create)
  477.                         logMsg("arptnew failed on %xn", 
  478. (int)ntohl(soInAddr->sin_addr.s_addr),
  479.                         0,0,0,0,0);
  480.                  return (0);
  481.             }
  482.             la = (struct llinfo_arp *)rt->rt_llinfo;
  483.             arptfree(la);
  484.     }
  485.             break;
  486.         }
  487. return (0);
  488.    }
  489. /*
  490.  * cifproxyarp - Delete the proxy ARP entry for the peer.
  491.  */
  492. int
  493. cifproxyarp(unit, hisaddr)
  494.     int unit;
  495.     u_long hisaddr;
  496. {
  497.     struct arpreq arpreq;
  498.     BZERO((char *)&arpreq, sizeof(arpreq));
  499.     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
  500.     arpreq.arp_pa.sa_len = sizeof (struct sockaddr_in);
  501.     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
  502.     pppArpCmd (SIOCDARP, &arpreq);
  503.     return 1;
  504. }
  505. /*
  506.  * get_ether_addr - get the hardware address of an interface on the
  507.  * the same subnet as ipaddr.
  508.  */
  509. #define MAX_IFS 32
  510. int
  511. get_ether_addr(ipaddr, hwaddr)
  512.     u_long ipaddr;
  513.     struct sockaddr *hwaddr;
  514. {
  515.     struct ifnet *ifp;
  516.     struct ifreq *ifr, *ifend;
  517.     u_long ina, mask;
  518.     struct ifreq ifreq;
  519.     struct ifconf ifc;
  520.     struct ifreq ifs[MAX_IFS];
  521.     ifc.ifc_len = sizeof(ifs);
  522.     ifc.ifc_req = ifs;
  523.     if (ioctl(ppp_if[ppp_unit]->s, SIOCGIFCONF, (int) &ifc) < 0) {
  524. syslog(LOG_ERR, "ioctl(SIOCGIFCONF) error");
  525. return 0;
  526.     }
  527.     /*
  528.      * Scan through looking for an interface with an Internet
  529.      * address on the same subnet as `ipaddr'.
  530.      */
  531.     ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
  532.     for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)((char *)ifr +
  533. sizeof(ifr->ifr_name) + 
  534. ifr->ifr_addr.sa_len)) 
  535. {
  536. if (ifr->ifr_addr.sa_family == AF_INET) {
  537.     ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
  538.     strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
  539.     /*
  540.      * Check that the interface is up, and not point-to-point
  541.      * or loopback.
  542.      */
  543.     if (ioctl(ppp_if[ppp_unit]->s, SIOCGIFFLAGS, (int) &ifreq) < 0)
  544. continue;
  545.     if ((ifreq.ifr_flags &
  546.  (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
  547.  != (IFF_UP|IFF_BROADCAST))
  548. continue;
  549.     /*
  550.      * Get its netmask and check that it's on the right subnet.
  551.      */
  552.     if (ioctl(ppp_if[ppp_unit]->s, SIOCGIFNETMASK, (int) &ifreq) < 0)
  553. continue;
  554.             mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
  555.     if ((ipaddr & mask) != (ina & mask))
  556. continue;
  557.     break;
  558. }
  559.     }
  560.     if (ifr >= ifend)
  561. return 0;
  562.     if ((ifp = ifunit (ifr->ifr_name)) == NULL)
  563. return 0;
  564.     syslog(LOG_INFO, "found interface %s for proxy arp", ifr->ifr_name);
  565.     /* stuff the ethernet hw address for the arp add call */
  566.     bcopy ((caddr_t) ((struct arpcom *)ifp)->ac_enaddr,
  567. (caddr_t) hwaddr->sa_data, sizeof(((struct arpcom *)ifp)->ac_enaddr));
  568.     hwaddr->sa_family = AF_UNSPEC;
  569.     return 1;
  570. }
  571. /*
  572.  * ppp_available - check whether the system has any ppp interfaces
  573.  * (in fact we check whether we can do an ioctl on ppp0).
  574.  */
  575. int
  576. ppp_available()
  577. {
  578. #ifdef notyet
  579.     int s, ok;
  580.     struct ifreq ifr;
  581.     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  582.         return 1;               /* can't tell - maybe we're not root */
  583.     strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
  584.     ok = ioctl(s, SIOCGIFFLAGS, (int) &ifr) >= 0;
  585.     close(s);
  586.     return ok;
  587. #else /* notyet */
  588.     return 1;
  589. #endif /* notyet */
  590. }
  591. #ifdef __STDC__
  592. #include <stdarg.h>
  593. void
  594. syslog(int level, char *fmt, ...)
  595. {
  596.     va_list pvar;
  597.     char buf[256];
  598.     va_start(pvar, fmt);
  599.     vsprintf(buf, fmt, pvar);
  600.     va_end(pvar);
  601.     printf("ppp%d: %srn", ppp_unit, buf);
  602. }
  603. #else /* __STDC__ */
  604. #include <varargs.h>
  605. void
  606. syslog(level, fmt, va_alist)
  607. int level;
  608. char *fmt;
  609. va_dcl
  610. {
  611.     va_list pvar;
  612.     char buf[256];
  613.     va_start(pvar);
  614.     vprintf(fmt, pvar);
  615.     va_end(pvar);
  616.     printf("ppp%d: %srn", ppp_unit, buf);
  617. }
  618. #endif /* __STDC__ */
  619. char *stringdup(in)
  620. char *in;
  621. {
  622.     char* dup;
  623.     if ((dup = (char *)malloc(strlen(in) + 1)) == NULL)
  624. return NULL;
  625.     (void) strcpy(dup, in);
  626.     return (dup);
  627. }