* sys-bsd.c - System-dependent procedures for setting up
* PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
* Copyright (c) 1989 Carnegie Mellon University.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by Carnegie Mellon University. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
static char rcsid
[] = "$Id: sys-bsd.c,v 1.2 1993/12/14 05:41:11 paulus Exp $";
static int initdisc
; /* Initial TTY discipline */
* establish_ppp - Turn the serial port into a ppp interface.
if (ioctl(fd
, TIOCGETD
, &initdisc
) < 0) {
syslog(LOG_ERR
, "ioctl(TIOCGETD): %m");
if (ioctl(fd
, TIOCSETD
, &pppdisc
) < 0) {
syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
* Find out which interface we were given.
if (ioctl(fd
, PPPIOCGUNIT
, &ifunit
) < 0) {
syslog(LOG_ERR
, "ioctl(PPPIOCGUNIT): %m");
* disestablish_ppp - Restore the serial port to normal operation.
* This shouldn't call die() because it's called from die().
if (ioctl(fd
, TIOCSETD
, &initdisc
) < 0)
syslog(LOG_ERR
, "ioctl(TIOCSETD): %m");
* output - Output PPP packet.
MAINDEBUG((LOG_WARNING
, "output: unit != 0!"));
if (write(fd
, p
, len
) < 0) {
syslog(LOG_ERR
, "write: %m");
* read_packet - get a PPP packet from the serial device.
if ((len
= read(fd
, buf
, MTU
+ DLLHEADERLEN
)) < 0) {
if (errno
== EWOULDBLOCK
) {
MAINDEBUG((LOG_DEBUG
, "read(fd): EWOULDBLOCK"));
syslog(LOG_ERR
, "read(fd): %m");
* ppp_send_config - configure the transmit characteristics of
ppp_send_config(unit
, mtu
, asyncmap
, pcomp
, accomp
)
strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
if (ioctl(s
, SIOCSIFMTU
, (caddr_t
) &ifr
) < 0) {
syslog(LOG_ERR
, "ioctl(SIOCSIFMTU): %m");
if (ioctl(fd
, PPPIOCSASYNCMAP
, (caddr_t
) &asyncmap
) < 0) {
syslog(LOG_ERR
, "ioctl(PPPIOCSASYNCMAP): %m");
if (ioctl(fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
x
= pcomp
? x
| SC_COMP_PROT
: x
&~ SC_COMP_PROT
;
x
= accomp
? x
| SC_COMP_AC
: x
&~ SC_COMP_AC
;
if (ioctl(fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
* ppp_recv_config - configure the receive-side characteristics of
* the ppp interface. At present this does nothing.
ppp_recv_config(unit
, mru
, asyncmap
, pcomp
, accomp
)
if (ioctl(fd
, PPPIOCSRASYNCMAP
, (caddr_t
) &asyncmap
) < 0) {
syslog(LOG_ERR
, "ioctl(PPPIOCSRASYNCMAP): %m");
if (ioctl(fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
x
= !accomp
? x
| SC_REJ_COMP_AC
: x
&~ SC_REJ_COMP_AC
;
if (ioctl(fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
* sifvjcomp - config tcp header compression
sifvjcomp(u
, vjcomp
, cidcomp
)
if (ioctl(fd
, PPPIOCGFLAGS
, (caddr_t
) &x
) < 0) {
syslog(LOG_ERR
, "ioctl (PPPIOCGFLAGS): %m");
x
= vjcomp
? x
| SC_COMP_TCP
: x
&~ SC_COMP_TCP
;
x
= cidcomp
? x
& ~SC_NO_TCP_CCID
: x
| SC_NO_TCP_CCID
;
if(ioctl(fd
, PPPIOCSFLAGS
, (caddr_t
) &x
) < 0) {
syslog(LOG_ERR
, "ioctl(PPPIOCSFLAGS): %m");
* sifup - Config the interface up.
strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
if (ioctl(s
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
syslog(LOG_ERR
, "ioctl (SIOCGIFFLAGS): %m");
if (ioctl(s
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
syslog(LOG_ERR
, "ioctl(SIOCSIFFLAGS): %m");
* sifdown - Config the interface down.
strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
if (ioctl(s
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) < 0) {
syslog(LOG_ERR
, "ioctl (SIOCGIFFLAGS): %m");
ifr
.ifr_flags
&= ~IFF_UP
;
if (ioctl(s
, SIOCSIFFLAGS
, (caddr_t
) &ifr
) < 0) {
syslog(LOG_ERR
, "ioctl(SIOCSIFFLAGS): %m");
* SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
#define SET_SA_FAMILY(addr, family) \
BZERO((char *) &(addr), sizeof(addr)); \
addr.sa_family = (family); \
addr.sa_len = sizeof(addr);
* sifaddr - Config the interface IP addresses and netmask.
strncpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
SET_SA_FAMILY(ifra
.ifra_mask
, AF_INET
);
((struct sockaddr_in
*) &ifra
.ifra_mask
)->sin_addr
.s_addr
= m
;
BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
if (ioctl(s
, SIOCAIFADDR
, (caddr_t
) &ifra
) < 0) {
syslog(LOG_ERR
, "ioctl(SIOCAIFADDR): %m");
syslog(LOG_WARNING
, "ioctl(SIOCAIFADDR): Address already exists");
* cifaddr - Clear the interface IP addresses, and delete routes
* through the interface if possible.
strncpy(ifra
.ifra_name
, ifname
, sizeof(ifra
.ifra_name
));
SET_SA_FAMILY(ifra
.ifra_addr
, AF_INET
);
((struct sockaddr_in
*) &ifra
.ifra_addr
)->sin_addr
.s_addr
= o
;
SET_SA_FAMILY(ifra
.ifra_broadaddr
, AF_INET
);
((struct sockaddr_in
*) &ifra
.ifra_broadaddr
)->sin_addr
.s_addr
= h
;
BZERO(&ifra
.ifra_mask
, sizeof(ifra
.ifra_mask
));
if (ioctl(s
, SIOCDIFADDR
, (caddr_t
) &ifra
) < 0) {
syslog(LOG_WARNING
, "ioctl(SIOCDIFADDR): %m");
* sifdefaultroute - assign a default route through the address given.
SET_SA_FAMILY(rt
.rt_dst
, AF_INET
);
SET_SA_FAMILY(rt
.rt_gateway
, AF_INET
);
((struct sockaddr_in
*) &rt
.rt_gateway
)->sin_addr
.s_addr
= g
;
rt
.rt_flags
= RTF_GATEWAY
;
if (ioctl(s
, SIOCADDRT
, &rt
) < 0) {
syslog(LOG_ERR
, "default route ioctl(SIOCADDRT): %m");
* cifdefaultroute - delete a default route through the address given.
SET_SA_FAMILY(rt
.rt_dst
, AF_INET
);
SET_SA_FAMILY(rt
.rt_gateway
, AF_INET
);
((struct sockaddr_in
*) &rt
.rt_gateway
)->sin_addr
.s_addr
= g
;
rt
.rt_flags
= RTF_GATEWAY
;
if (ioctl(s
, SIOCDELRT
, &rt
) < 0)
syslog(LOG_WARNING
, "default route ioctl(SIOCDELRT): %m");
* sifproxyarp - Make a proxy ARP entry for the peer.
sifproxyarp(unit
, hisaddr
)
BZERO(&arpreq
, sizeof(arpreq
));
* Get the hardware address of an interface on the same subnet
if (!get_ether_addr(hisaddr
, &arpreq
.arp_ha
)) {
syslog(LOG_ERR
, "Cannot determine ethernet address for proxy ARP");
SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
arpreq
.arp_flags
= ATF_PERM
| ATF_PUBL
;
if (ioctl(s
, SIOCSARP
, (caddr_t
)&arpreq
) < 0) {
syslog(LOG_ERR
, "ioctl(SIOCSARP): %m");
* cifproxyarp - Delete the proxy ARP entry for the peer.
cifproxyarp(unit
, hisaddr
)
BZERO(&arpreq
, sizeof(arpreq
));
SET_SA_FAMILY(arpreq
.arp_pa
, AF_INET
);
((struct sockaddr_in
*) &arpreq
.arp_pa
)->sin_addr
.s_addr
= hisaddr
;
if (ioctl(s
, SIOCDARP
, (caddr_t
)&arpreq
) < 0) {
syslog(LOG_WARNING
, "ioctl(SIOCDARP): %m");
* get_ether_addr - get the hardware address of an interface on the
* the same subnet as ipaddr.
get_ether_addr(ipaddr
, hwaddr
)
struct ifreq
*ifr
, *ifend
, *ifp
;
struct ifreq ifs
[MAX_IFS
];
ifc
.ifc_len
= sizeof(ifs
);
if (ioctl(s
, SIOCGIFCONF
, &ifc
) < 0) {
syslog(LOG_ERR
, "ioctl(SIOCGIFCONF): %m");
* Scan through looking for an interface with an Internet
* address on the same subnet as `ipaddr'.
ifend
= (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ) {
if (ifr
->ifr_addr
.sa_family
== AF_INET
) {
ina
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
strncpy(ifreq
.ifr_name
, ifr
->ifr_name
, sizeof(ifreq
.ifr_name
));
* Check that the interface is up, and not point-to-point
if (ioctl(s
, SIOCGIFFLAGS
, &ifreq
) < 0)
(IFF_UP
|IFF_BROADCAST
|IFF_POINTOPOINT
|IFF_LOOPBACK
|IFF_NOARP
))
!= (IFF_UP
|IFF_BROADCAST
))
* Get its netmask and check that it's on the right subnet.
if (ioctl(s
, SIOCGIFNETMASK
, &ifreq
) < 0)
mask
= ((struct sockaddr_in
*) &ifr
->ifr_addr
)->sin_addr
.s_addr
;
if ((ipaddr
& mask
) != (ina
& mask
))
ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
+ ifr
->ifr_addr
.sa_len
);
syslog(LOG_INFO
, "found interface %s for proxy arp", ifr
->ifr_name
);
* Now scan through again looking for a link-level address
for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ) {
if (strcmp(ifp
->ifr_name
, ifr
->ifr_name
) == 0
&& ifr
->ifr_addr
.sa_family
== AF_LINK
) {
* Found the link-level address - copy it out
dla
= (struct sockaddr_dl
*)&ifr
->ifr_addr
;
hwaddr
->sa_len
= sizeof(struct sockaddr
);
hwaddr
->sa_family
= AF_UNSPEC
;
BCOPY(LLADDR(dla
), hwaddr
->sa_data
, dla
->sdl_alen
);
ifr
= (struct ifreq
*) ((char *)&ifr
->ifr_addr
+ ifr
->ifr_addr
.sa_len
);
* ppp_available - check whether the system has any ppp interfaces
* (in fact we check whether we can do an ioctl on ppp0).
if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
return 1; /* can't tell - maybe we're not root */
strncpy(ifr
.ifr_name
, "ppp0", sizeof (ifr
.ifr_name
));
ok
= ioctl(s
, SIOCGIFFLAGS
, (caddr_t
) &ifr
) >= 0;