static char sccsid
[] = "@(#)startup.c 4.6 (Berkeley) %G%";
* Routing Table Management Daemon
int lookforinterfaces
= 1;
int externalinterfaces
= 0; /* # of remote and local interfaces */
int gateway
= 0; /* 1 if we are a gateway to parts beyond */
* Probe the kernel through /dev/kmem to find the network
* interfaces which have configured themselves. If the
* interface is present but not yet up (for example an
* ARPANET IMP), set the lookforinterfaces flag so we'll
* come back later and look again.
char name
[32], *cp
, *index();
if (nl
[N_IFNET
].n_value
== 0) {
printf("ifnet: not in namelist\n");
kmem
= open("/dev/kmem", 0);
if (lseek(kmem
, (long)nl
[N_IFNET
].n_value
, 0) == -1 ||
read(kmem
, (char *)&next
, sizeof (next
)) != sizeof (next
)) {
printf("ifnet: error reading kmem\n");
if (lseek(kmem
, (long)next
, 0) == -1 ||
read(kmem
, (char *)&ifs
, sizeof (ifs
)) != sizeof (ifs
)) {
if ((ifs
.if_flags
& IFF_UP
) == 0) {
/* already known to us? */
if (if_ifwithaddr(&ifs
.if_addr
))
/* argh, this'll have to change sometime */
if (ifs
.if_addr
.sa_family
!= AF_INET
)
/* no one cares about software loopback interfaces */
if (ifs
.if_net
== LOOPBACKNET
)
ifp
= (struct interface
*)malloc(sizeof (struct interface
));
printf("routed: out of memory\n");
* Count the # of directly connected networks
* and point to point links which aren't looped
* back to ourself. This is used below to
* decide if we should be a routing ``supplier''.
if ((ifs
.if_flags
& IFF_POINTOPOINT
) == 0 ||
if_ifwithaddr(&ifs
.if_dstaddr
) == 0)
if ((ifs
.if_flags
& IFF_LOCAL
) == 0 && gateway
== 0) {
* If we have an interface to a non-local network,
* we are a candidate for use as a gateway.
lseek(kmem
, ifs
.if_name
, 0);
read(kmem
, name
, sizeof (name
));
name
[sizeof (name
) - 1] = '\0';
*cp
++ = ifs
.if_unit
+ '0';
ifp
->int_name
= malloc(strlen(name
) + 1);
if (ifp
->int_name
== 0) {
fprintf(stderr
, "routed: ifinit: out of memory\n");
strcpy(ifp
->int_name
, name
);
ifp
->int_addr
= ifs
.if_addr
;
ifp
->int_flags
= ifs
.if_flags
| IFF_INTERFACE
;
/* this works because broadaddr overlaps dstaddr */
ifp
->int_broadaddr
= ifs
.if_broadaddr
;
ifp
->int_net
= ifs
.if_net
;
if (externalinterfaces
> 1 && supplier
< 0)
execv("/etc/routed", argv0
);
if (ifp
->int_flags
& IFF_POINTOPOINT
)
bzero((char *)&net
, sizeof (net
));
net
.sin_family
= AF_INET
;
net
.sin_addr
= inet_makeaddr(ifp
->int_net
, INADDR_ANY
);
dst
= (struct sockaddr
*)&net
;
rtadd(dst
, &ifp
->int_addr
, ifp
->int_metric
,
ifp
->int_flags
& (IFF_INTERFACE
|IFF_PASSIVE
|IFF_REMOTE
));
* As a concession to the ARPANET we read a list of gateways
* from /etc/gateways and add them to our tables. This file
* exists at each ARPANET gateway and indicates a set of ``remote''
* gateways (i.e. a gateway which we can't immediately determine
* if it's present or not as we can do for those directly connected
* at the hardware level). If a gateway is marked ``passive''
* in the file, then we assume it doesn't have a routing process
* of our design and simply assume it's always present. Those
* not marked passive are treated as if they were directly
* connected -- they're added into the interface list so we'll
* send them routing updates.
struct sockaddr_in dst
, gate
;
char *type
, *dname
, *gname
, *qual
, buf
[BUFSIZ
];
fp
= fopen("/etc/gateways", "r");
gname
= buf
+ ((BUFSIZ
- 64) / 3);
type
= buf
+ (((BUFSIZ
- 64) * 2) / 3);
bzero((char *)&dst
, sizeof (dst
));
bzero((char *)&gate
, sizeof (gate
));
bzero((char *)&route
, sizeof(route
));
/* format: {net | host} XX gateway XX metric DD [passive]\n */
fscanf((fp), "%s %s gateway %s metric %d %s\n", \
type, dname, gname, &metric, qual)
if (readentry(fp
) == EOF
)
if (!getnetorhostname(type
, dname
, &dst
))
if (!gethostnameornumber(gname
, &gate
))
if (strcmp(qual
, "passive") == 0) {
* Passive entries aren't placed in our tables,
* only the kernel's, so we don't copy all of the
* external routing information within a net.
* Internal machines should use the default
* route to a suitable gateway (like us).
route
.rt_dst
= *(struct sockaddr
*) &dst
;
route
.rt_router
= *(struct sockaddr
*) &gate
;
if (strcmp(type
, "host") == 0)
route
.rt_flags
|= RTF_HOST
;
route
.rt_flags
|= RTF_GATEWAY
;
(void) ioctl(s
, SIOCADDRT
, (char *)&route
.rt_rt
);
/* assume no duplicate entries */
ifp
= (struct interface
*)malloc(sizeof (*ifp
));
bzero((char *)ifp
, sizeof (*ifp
));
ifp
->int_flags
= IFF_REMOTE
;
/* can't identify broadcast capability */
ifp
->int_net
= inet_netof(dst
.sin_addr
);
if (strcmp(type
, "host") == 0) {
ifp
->int_flags
|= IFF_POINTOPOINT
;
ifp
->int_dstaddr
= *((struct sockaddr
*)&dst
);
ifp
->int_addr
= *((struct sockaddr
*)&gate
);
ifp
->int_metric
= metric
;
getnetorhostname(type
, name
, sin
)
if (strcmp(type
, "net") == 0) {
struct netent
*np
= getnetbyname(name
);
if (np
->n_addrtype
!= AF_INET
)
sin
->sin_family
= AF_INET
;
sin
->sin_addr
= inet_makeaddr(n
, INADDR_ANY
);
if (strcmp(type
, "host") == 0) {
struct hostent
*hp
= gethostbyname(name
);
sin
->sin_addr
.s_addr
= inet_addr(name
);
if (hp
->h_addrtype
!= AF_INET
)
bcopy(hp
->h_addr
, &sin
->sin_addr
, hp
->h_length
);
sin
->sin_family
= AF_INET
;
gethostnameornumber(name
, sin
)
hp
= gethostbyname(name
);
bcopy(hp
->h_addr
, &sin
->sin_addr
, hp
->h_length
);
sin
->sin_family
= hp
->h_addrtype
;
sin
->sin_addr
.s_addr
= inet_addr(name
);
sin
->sin_family
= AF_INET
;
return (sin
->sin_addr
.s_addr
!= -1);