Subject: Routing question
To: None <tech-net@NetBSD.ORG>
From: Martin Husemann <martin@rumolt.teuto.de>
List: tech-net
Date: 02/23/1997 12:03:11
I stumbled accross a small problem when I got the connection to my ISP
changed from slip (via modem) to PPP (via ISDN). I have a ppp interface
always up, with a default route to that interface. When the connection
comes up pppd does address negotiation and reconfigures the interface.
Please ignore the unusual PPP setup for the moment, I have attached a
small script and demo program to see the effect without any pppd interaction.

If you have a spare ppp0 interface, just compile the program (with -o demo)
and run the script. This gives you output similar to this:

---- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< -----
removing default route (if any)
 
ppp0 set to start configuration:
ppp0: flags=8010<POINTOPOINT,MULTICAST>
	inet 194.40.112.230 --> 194.40.112.250 netmask 0xffffffff 
add net default: gateway 194.40.112.250
 
routing table before demo program:
Routing tables

Internet:
Destination      Gateway            Flags 
default          194.40.112.250     UG     
localhost        127.0.0.1          UH     
up-vision-net    192.168.110.42     UG     
emmas.up-vision. 194.77.123.129     UH     
194.40.112.250   194.40.112.230     UH     
194.77.123.128   link#1             U      
rumolt           127.0.0.1          UGH    
194.77.123.143   link#1             UH     
 
now running demo program
 
new ppp0 configuration:
ppp0: flags=8010<POINTOPOINT,MULTICAST>
	inet 194.40.112.248 --> 194.40.112.249 netmask 0xffffffff 
 
routing table is now:
Routing tables

Internet:
Destination      Gateway            Flags 
default          194.40.112.250     UG     
localhost        127.0.0.1          UH     
up-vision-net    192.168.110.42     UG     
emmas.up-vision. 194.77.123.129     UH     
194.40.112.249   194.40.112.248     UH     
194.77.123.128   link#1             U      
rumolt           127.0.0.1          UGH    
194.77.123.143   link#1             UH     
---- >8 --------- >8 --------- >8 --------- >8 --------- >8 --------- >8 -----

I am wondering, if the new setup of ppp0 by the demo program should delete
the defaultroute. According to "TCP/IP Illustrated" the ioctl's should remove
all routes based on the old address. It doesn't do so for the defaultroute
obviously. This may be desirable or may not, I'm not sure.

Actualy, the case that bit me is a more subtle: Since my service provider
always assigns the same address to his side of the link I had the remote
address and the defaultroute set to the same value, that comes out of the
address negotiation. You can simulate this by changing the commented DEST
settings in the script. This leaves you with a correct default route as shown
by "route show" - but it doesn't work! I guess there are two ifaddr structs
with the same address, one with reference from the old defaultroute and no
connection to ppp0, and another from the new ppp0 configuration but no
connection to the defaultroute entry in the routing tree. You have to do
"route delete default" and then "route add default ...." with the same
address you just deleted the default route to - and magically it works again.

Yes, this is pilot-error (and I know how to modify my setup), but the 
"route show" output is realy confusing!


Any comments?


Martin


The script to produce the above output:
---- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< -----
#!/bin/sh

DEST=194.40.112.250
#DEST=194.40.112.249

echo "removing default route (if any)"
route delete default > /dev/null 2>&1

ifconfig ppp0 inet 194.40.112.230 $DEST netmask 255.255.255.255
echo " "
echo "ppp0 set to start configuration:"
ifconfig ppp0
route add default $DEST
echo " "
echo "routing table before demo program:"
route show
echo " "

echo "now running demo program"
./demo

echo " "
echo "new ppp0 configuration:"
ifconfig ppp0
echo " "
echo "routing table is now:"
route show
---- >8 --------- >8 --------- >8 --------- >8 --------- >8 --------- >8 -----

The program "demo.c", compile with something like (Hmm, shouldn't specify
the addresses like this, I'm on a little endian machine, swap bytes manualy
or insert hton/ntoh macros if you like. Sorry, but it's just a demo...)
cc -Wall -O2 -o demo demo.c
---- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< -----
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>

#define SET_SA_FAMILY(addr, family)		\
    bzero((char *) &(addr), sizeof(addr));	\
    addr.sa_family = (family); 			\
    addr.sa_len = sizeof(addr);

#define LOCALIP		0xf87028c2
#define REMOTEIP	0xf97028c2
#define NETMASK		0xffffffff
    
int main()
{
    int sockfd;
    struct ifaliasreq ifra;
    struct ifreq ifrd;

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	return 1;

    strncpy(ifrd.ifr_name, "ppp0", sizeof (ifrd.ifr_name));
    if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifrd) < 0) {
    	fprintf(stderr, "interface ppp0 not configured\n");
    	close(sockfd);
    	return 1;
    }

    strncpy(ifra.ifra_name, "ppp0", sizeof(ifra.ifra_name));
    SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
    ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = LOCALIP;
    SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
    ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = REMOTEIP;
    SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
    ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = NETMASK;

    strncpy(ifrd.ifr_name, "ppp0", sizeof(ifrd.ifr_name));
    SET_SA_FAMILY(ifrd.ifr_addr, AF_INET);
    if (ioctl(sockfd, SIOCGIFADDR, (caddr_t) &ifrd) != -1)
    	ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifrd);

    if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
	if (errno != EEXIST) {
	    perror("Couldn't set interface address");
	    return 1;
	}
	fprintf(stderr, "Warning: Couldn't set interface address: Address already exists\n");
    }
    close(sockfd);

    return 0;
}
---- >8 --------- >8 --------- >8 --------- >8 --------- >8 --------- >8 -----