Äèïëîìíàÿ ðàáîòà: Àëãîðèòìè ìàðøðóòèçàö³¿ â ìåðåæàõ
FD_SET(rip_sock, &fdbits);
if (sock_max <= rip_sock)
sock_max = rip_sock+1;
}
for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
if (ifp->int_rip_sock >= 0) {
FD_SET(ifp->int_rip_sock,
&fdbits);
if (sock_max <=
ifp->int_rip_sock)
sock_max =
ifp->int_rip_sock+1;
}
}
if (rdisc_sock >= 0) {
FD_SET(rdisc_sock, &fdbits);
if (sock_max <= rdisc_sock)
sock_max = rdisc_sock+1;
}
}
void
fix_sock(int sock,
char *name)
{
int on;
#define MIN_SOCKBUF (4*1024)
static int rbuf;
if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
logbad(1, "fcntl(%s) O_NONBLOCK: %s",
name, strerror(errno));
on = 1;
if (setsockopt(sock, SOL_SOCKET,SO_BROADCAST,
&on,sizeof(on)) < 0)
msglog("setsockopt(%s,SO_BROADCAST): %s",
name, strerror(errno));
#ifdef USE_PASSIFNAME
on = 1;
if (setsockopt(sock, SOL_SOCKET, SO_PASSIFNAME,
&on,sizeof(on)) < 0)
msglog("setsockopt(%s,SO_PASSIFNAME):
%s",
name, strerror(errno));
#endif
if (rbuf >= MIN_SOCKBUF) {
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
&rbuf, sizeof(rbuf)) < 0)
msglog("setsockopt(%s,SO_RCVBUF=%d):
%s",
name, rbuf, strerror(errno));
} else {
for (rbuf = 60*1024; ; rbuf -= 4096) {
if (setsockopt(sock, SOL_SOCKET,
SO_RCVBUF,
&rbuf, sizeof(rbuf))
== 0) {
trace_act("RCVBUF=%d",
rbuf);
break;
}
if (rbuf < MIN_SOCKBUF) {
msglog("setsockopt(%s,SO_RCVBUF
= %d): %s",
name, rbuf,
strerror(errno));
break;
}
}
}
}
/* get a rip socket
*/
static int /* <0 or file
descriptor */
get_rip_sock(naddr addr,
int serious) /* 1=failure to bind is serious
*/
{
struct sockaddr_in sin;
unsigned char ttl;
int s;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
BADERR(1,"rip_sock = socket()");
bzero(&sin,sizeof(sin));
#ifdef _HAVE_SIN_LEN
sin.sin_len = sizeof(sin);
#endif
sin.sin_family = AF_INET;
sin.sin_port = htons(RIP_PORT);
sin.sin_addr.s_addr = addr;
if (bind(s, (struct sockaddr *)&sin,sizeof(sin)) < 0) {
if (serious)
BADERR(errno != EADDRINUSE,
"bind(rip_sock)");
return -1;
}
fix_sock(s,"rip_sock");
ttl = 1;
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof(ttl)) < 0)
DBGERR(1,"rip_sock
setsockopt(IP_MULTICAST_TTL)");
return s;
}
/* turn off main RIP socket */
void
rip_off(void)
{
struct interface *ifp;
register naddr addr;
if (rip_sock >= 0 && !mhome) {
trace_act("turn off RIP");
(void)close(rip_sock);
rip_sock = -1;
/* get non-broadcast sockets to listen to queries.
*/
for (ifp = ifnet; ifp != 0; ifp = ifp->int_next)
{
if (ifp->int_state & IS_REMOTE)
continue;
if (ifp->int_rip_sock < 0) {
addr =
((ifp->int_if_flags & IFF_POINTOPOINT)
? ifp->int_dstaddr
:
ifp->int_addr);
ifp->int_rip_sock =
get_rip_sock(addr, 0);
}
}
fix_select();
age(0);
}
}
/* turn on RIP multicast input via an interface
*/
static void
rip_mcast_on(struct interface *ifp)
{
struct ip_mreq m;
if (!IS_RIP_IN_OFF(ifp->int_state)
&& (ifp->int_if_flags & IFF_MULTICAST)
#ifdef MCAST_PPP_BUG
&& !(ifp->int_if_flags & IFF_POINTOPOINT)
#endif
&& !(ifp->int_state & IS_ALIAS)) {
m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
m.imr_interface.s_addr = ((ifp->int_if_flags
& IFF_POINTOPOINT)
?
ifp->int_dstaddr
:
ifp->int_addr);
if (setsockopt(rip_sock,IPPROTO_IP,
IP_ADD_MEMBERSHIP,
&m, sizeof(m)) < 0)
LOGERR("setsockopt(IP_ADD_MEMBERSHIP
RIP)");
}
}
/* Prepare socket used for RIP.
*/
void
rip_on(struct interface *ifp)
{
/* If the main RIP socket is already alive, only start
receiving
* multicasts for this interface.
*/
if (rip_sock >= 0) {
if (ifp != 0)
rip_mcast_on(ifp);
return;
}
/* If the main RIP socket is off and it makes sense to turn it
on,
* then turn it on for all of the interfaces.
*/
if (rip_interfaces > 0 && !rdisc_ok) {
trace_act("turn on RIP");
/* Close all of the query sockets so that we can
open
* the main socket. SO_REUSEPORT is not a solution,
* since that would let two daemons bind to the
broadcast
* socket.
*/
for (ifp = ifnet; ifp != 0; ifp = ifp->int_next)
{
if (ifp->int_rip_sock >= 0) {
(void)close(ifp->int_rip_sock);
ifp->int_rip_sock = -1;
}
}
rip_sock = get_rip_sock(INADDR_ANY, 1);
rip_sock_mcast = 0;
/* Do not advertise anything until we have heard
something
*/
if (next_bcast.tv_sec < now.tv_sec+MIN_WAITTIME)
next_bcast.tv_sec =
now.tv_sec+MIN_WAITTIME;
for (ifp = ifnet; ifp != 0; ifp = ifp->int_next)
{
ifp->int_query_time = NEVER;
rip_mcast_on(ifp);
}
ifinit_timer.tv_sec = now.tv_sec;
} else if (ifp != 0
&& !(ifp->int_state & IS_REMOTE)
&& ifp->int_rip_sock < 0) {
/* RIP is off, so ensure there are sockets on which
* to listen for queries.
*/
ifp->int_rip_sock =
get_rip_sock(ifp->int_addr, 0);
}
fix_select();
}
/* die if malloc(3) fails
*/
void *
rtmalloc(size_t size,
char *msg)
{
void *p = malloc(size);
if (p == 0)
logbad(1,"malloc() failed in %s", msg);
return p;
}
/* get a random instant in an interval
*/
void
intvl_random(struct timeval *tp, /* put value here */
u_long lo, /* value is after
this second */
u_long hi) /* and before this */
{
tp->tv_sec = (time_t)(hi == lo
? lo
: (lo + random() % ((hi - lo))));
tp->tv_usec = random() % 1000000;
}
void
timevaladd(struct timeval *t1,
struct timeval *t2)
{
t1->tv_sec += t2->tv_sec;
if ((t1->tv_usec += t2->tv_usec) > 1000000) {
t1->tv_sec++;
t1->tv_usec -= 1000000;
}
}
/* t1 = t2 - t3
*/
static void
timevalsub(struct timeval *t1,
struct timeval *t2,
struct timeval *t3)
{
t1->tv_sec = t2->tv_sec - t3->tv_sec;
if ((t1->tv_usec = t2->tv_usec - t3->tv_usec) < 0)
{
t1->tv_sec--;
Ñòðàíèöû: 1, 2, 3, 4, 5, 6 |