FreeBSD/sbin/routed/rdisc.c
/* read packets from the router discovery socket
 */
read packets from the router discovery socket
read packets from the router discovery socket
void
read_d(void)
{
	static struct msg_limit bad_asize, bad_len;
#ifdef USE_PASSIFNAME
	static struct msg_limit  bad_name;
#endif
	struct sockaddr_in from;
	int n, fromlen, cc, hlen;
	struct {
#ifdef USE_PASSIFNAME
		char	ifname[IFNAMSIZ];
#endif
		union {
			struct ip ip;
			u_char	b[512];
		} pkt;
	} buf;
	union ad_u *p;
	n_long *wp;
	struct interface *ifp;
	for (;;) {
		fromlen = sizeof(from);
		cc = recvfrom(rdisc_sock, &buf, sizeof(buf), 0,
			      (struct sockaddr*)&from,
			      &fromlen);
		if (cc <= 0) {
			if (cc < 0 && errno != EWOULDBLOCK)
				LOGERR("recvfrom(rdisc_sock)");
			break;
		}
		if (fromlen != sizeof(struct sockaddr_in))
			logbad(1,"impossible recvfrom(rdisc_sock) fromlen=%d",
			       fromlen);
#ifdef USE_PASSIFNAME
		if ((cc -= sizeof(buf.ifname)) < 0)
			logbad(0,"missing USE_PASSIFNAME; only %d bytes",
			       cc+sizeof(buf.ifname));
#endif
		hlen = buf.pkt.ip.ip_hl << 2;
		if (cc < hlen + ICMP_MINLEN)
			continue;
		p = (union ad_u *)&buf.pkt.b[hlen];
		cc -= hlen;
#ifdef USE_PASSIFNAME
		ifp = ifwithname(buf.ifname, 0);
		if (ifp == NULL)
			msglim(&bad_name, from.sin_addr.s_addr,
			       "impossible rdisc if_ name %.*s",
			       IFNAMSIZ, buf.ifname);
#else
		ifp = ((from.sin_addr.s_addr == 0)
		       ? 0 : iflookup(from.sin_addr.s_addr));
#endif
		ifp = ck_icmp("Recv", from.sin_addr.s_addr, ifp,
			      buf.pkt.ip.ip_dst.s_addr, p, cc);
		if (ifp == NULL)
			continue;
		if (ifwithaddr(from.sin_addr.s_addr, 0, 0)) {
			trace_pkt("    "
				  "discard our own Router Discovery message");
			continue;
		}
		switch (p->icmp.icmp_type) {
		case ICMP_ROUTERADVERT:
			if (p->ad.icmp_ad_asize*4
			    < (int)sizeof(p->ad.icmp_ad_info[0])) {
				msglim(&bad_asize, from.sin_addr.s_addr,
				       "intolerable rdisc address size=%d",
				       p->ad.icmp_ad_asize);
				continue;
			}
			if (p->ad.icmp_ad_num == 0) {
				trace_pkt("    empty?");
				continue;
			}
			if (cc != (int)(sizeof(p->ad)
					- sizeof(p->ad.icmp_ad_info)
					+ (p->ad.icmp_ad_num
					   * sizeof(p->ad.icmp_ad_info[0])))) {
				msglim(&bad_len, from.sin_addr.s_addr,
				       "rdisc length %d does not match ad_num"
				       " %d", cc, p->ad.icmp_ad_num);
				continue;
			}
			if (supplier)
				continue;
			if (ifp->int_state & IS_NO_ADV_IN)
				continue;
			wp = &p->ad.icmp_ad_info[0].icmp_ad_addr;
			for (n = 0; n < p->ad.icmp_ad_num; n++) {
				parse_ad(from.sin_addr.s_addr,
					 wp[0], wp[1],
					 ntohs(p->ad.icmp_ad_life),
					 ifp);
				wp += p->ad.icmp_ad_asize;
			}
			break;
		case ICMP_ROUTERSOLICIT:
			if (!supplier)
				continue;
			if (ifp->int_state & IS_NO_ADV_OUT)
				continue;
			if (stopint)
				continue;
			send_adv(ifp, from.sin_addr.s_addr, 0);
			break;
		}
	}
	rdisc_sort();
}
void read_d ( void ) { static struct msg_limit bad_asize , bad_len ; #ifdef USE_PASSIFNAME static struct msg_limit bad_name ; #endif struct sockaddr_in from ; int n , fromlen , cc , hlen ; struct { #ifdef USE_PASSIFNAME char ifname [ IFNAMSIZ ] ; #endif union { struct ip ip ; u_char b [ 512 ] ; } pkt ; } buf ; union ad_u * p ; n_long * wp ; struct interface * ifp ; for ( ; ; ) { fromlen = sizeof ( from ) ; cc = recvfrom ( rdisc_sock , & buf , sizeof ( buf ) , 0 , ( struct sockaddr * ) & from , & fromlen ) ; if ( cc <= 0 ) { if ( cc < 0 && errno != EWOULDBLOCK ) LOGERR ( " " ) ; break ; } if ( fromlen != sizeof ( struct sockaddr_in ) ) logbad ( 1 , " " , fromlen ) ; #ifdef USE_PASSIFNAME if ( ( cc -= sizeof ( buf . ifname ) ) < 0 ) logbad ( 0 , " " , cc + sizeof ( buf . ifname ) ) ; #endif hlen = buf . pkt . ip . ip_hl << 2 ; if ( cc < hlen + ICMP_MINLEN ) continue ; p = ( union ad_u * ) & buf . pkt . b [ hlen ] ; cc -= hlen ; #ifdef USE_PASSIFNAME ifp = ifwithname ( buf . ifname , 0 ) ; if ( ifp == NULL ) msglim ( & bad_name , from . sin_addr . s_addr , " " , IFNAMSIZ , buf . ifname ) ; #else ifp = ( ( from . sin_addr . s_addr == 0 ) ? 0 : iflookup ( from . sin_addr . s_addr ) ) ; #endif ifp = ck_icmp ( " " , from . sin_addr . s_addr , ifp , buf . pkt . ip . ip_dst . s_addr , p , cc ) ; if ( ifp == NULL ) continue ; if ( ifwithaddr ( from . sin_addr . s_addr , 0 , 0 ) ) { trace_pkt ( " " " " ) ; continue ; } switch ( p -> icmp . icmp_type ) { case ICMP_ROUTERADVERT : if ( p -> ad . icmp_ad_asize * 4 < ( int ) sizeof ( p -> ad . icmp_ad_info [ 0 ] ) ) { msglim ( & bad_asize , from . sin_addr . s_addr , " " , p -> ad . icmp_ad_asize ) ; continue ; } if ( p -> ad . icmp_ad_num == 0 ) { trace_pkt ( " " ) ; continue ; } if ( cc != ( int ) ( sizeof ( p -> ad ) - sizeof ( p -> ad . icmp_ad_info ) + ( p -> ad . icmp_ad_num * sizeof ( p -> ad . icmp_ad_info [ 0 ] ) ) ) ) { msglim ( & bad_len , from . sin_addr . s_addr , " " " " , cc , p -> ad . icmp_ad_num ) ; continue ; } if ( supplier ) continue ; if ( ifp -> int_state & IS_NO_ADV_IN ) continue ; wp = & p -> ad . icmp_ad_info [ 0 ] . icmp_ad_addr ; for ( n = 0 ; n < p -> ad . icmp_ad_num ; n ++ ) { parse_ad ( from . sin_addr . s_addr , wp [ 0 ] , wp [ 1 ] , ntohs ( p -> ad . icmp_ad_life ) , ifp ) ; wp += p -> ad . icmp_ad_asize ; } break ; case ICMP_ROUTERSOLICIT : if ( ! supplier ) continue ; if ( ifp -> int_state & IS_NO_ADV_OUT ) continue ; if ( stopint ) continue ; send_adv ( ifp , from . sin_addr . s_addr , 0 ) ; break ; } } rdisc_sort ( ) ; }
read packets from the router discovery socket
read packets from the router discovery socket
/* If we could tell the interface on which a packet from
		 * address 0 arrived, we could deal with such solicitations.
		 */ /* XXX
			 * We should handle messages from address 0.
			 */ /* Respond with a point-to-point advertisement */