Exemple #1
0
int main(int argc, char **argv)
{
    int i;
    ethernet_t *ep;
    nwio_ethopt_t ethopt;
    nwio_ethstat_t ethstat;
    char hostname[1024];
    struct hostent *hostent;
    struct sigaction sa;
    nwio_ipconf_t ipconf;
    asynchio_t asyn;
    ssize_t n;
    ipaddr_t ip_addr;
    rarp46_t rarp46;
    int fd;
    int n_eths;

    program= argv[0];
    asyn_init(&asyn);

    debug= 0;
    i= 1;
    while (i < argc && argv[i][0] == '-') {
	char *opt= argv[i++]+1;

	if (opt[0] == '-' && opt[1] == 0) break;	/* -- */

	while (*opt != 0) switch (*opt++) {
	case 'd':
	    debug= 1;
	    if (between('0', *opt, '9')) debug= strtoul(opt, &opt, 10);
	    break;
	default:
	    usage();
	}
    }

    if ((n_eths= (argc - i)) == 0) usage();

#if __minix_vmd
    /* Minix-vmd can handle all nets at once using async I/O. */
    ethernets= allocate(n_eths * sizeof(ethernets[0]));
    for (i= 0; i < n_eths; i++) {
	ethernets[i].n= ifname2n(argv[argc - n_eths + i]);
    }
#else
    /* Minix forks n-1 times to handle each net in a process each. */
    for (i= 0; i < n_eths; i++) {
	if (i+1 < n_eths) {
	    switch (fork()) {
	    case -1:	fatal("fork()");
	    case 0:		break;
	    default:	continue;
	    }
	}
	ethernets= allocate(1 * sizeof(ethernets[0]));
	ethernets[0].n= ifname2n(argv[argc - n_eths + i]);
    }
    n_eths= 1;
#endif

    sa.sa_handler= onsig;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags= 0;
    sigaction(SIGUSR1, &sa, NULL);
    sigaction(SIGUSR2, &sa, NULL);

    for (i= 0; i < n_eths; i++) {
	ep= &ethernets[i];
	if ((ep->eth_fd= open(ethdev(ep->n), O_RDWR)) < 0) fatal(ethdev(ep->n));

	if (ioctl(ep->eth_fd, NWIOGETHSTAT, &ethstat) < 0) {
	    fprintf(stderr, "%s: %s: Unable to get eth statistics: %s\n",
		program, ethdev(ep->n), strerror(errno));
	    exit(1);
	}
	ep->eth_addr= ethstat.nwes_addr;
	if (debug >= 1) {
	    printf("%s: Ethernet address is %s\n",
		ethdev(ep->n), ether_ntoa(&ep->eth_addr));
	}

	ethopt.nweo_flags= NWEO_COPY | NWEO_EN_LOC | NWEO_EN_BROAD |
		NWEO_TYPESPEC;
	ethopt.nweo_type= HTONS(ETH_RARP_PROTO);

	if (ioctl(ep->eth_fd, NWIOSETHOPT, &ethopt) < 0) {
	    fprintf(stderr, "%s: %s: Unable to set eth options: %s\n",
		program, ethdev(ep->n), strerror(errno));
	    exit(1);
	}

	/* What are my address and netmask? */
	if ((fd= open(ipdev(ep->n), O_RDWR)) < 0) fatal(ipdev(ep->n));
	if (ioctl(fd, NWIOGIPCONF, &ipconf) < 0) fatal(ipdev(ep->n));

	ep->ip_addr= ipconf.nwic_ipaddr;
	ep->ip_mask= ipconf.nwic_netmask;
	close(fd);
	if (debug >= 1) {
	    printf("%s: IP address is %s / ",
		ipdev(ep->n), inet_ntoa(ep->ip_addr));
	    printf("%s\n", inet_ntoa(ep->ip_mask));
	}
    }

    /* Wait for RARP requests, reply, repeat. */
    for(;;) {
	fflush(NULL);

	/* Wait for a RARP request. */
	for (i= 0; i < n_eths; i++) {
	    ep= &ethernets[i];

	    n= asyn_read(&asyn, ep->eth_fd, ep->packet, sizeof(ep->packet));
	    if (n != -1) break;
	    if (errno != EINPROGRESS) {
		report(ethdev(ep->n));
		sleep(10);
	    }
	}

	/* RARP request? */
	if (i < n_eths
	    && n >= sizeof(rarp46)
	    && (memcpy(&rarp46, ep->packet, sizeof(rarp46)), 1)
	    && rarp46.a46_hdr == HTONS(RARP_ETHERNET)
	    && rarp46.a46_pro == HTONS(ETH_IP_PROTO)
	    && rarp46.a46_hln == 6
	    && rarp46.a46_pln == 4
	    && rarp46.a46_op == HTONS(RARP_REQUEST)
	) {
	    if ((ether_ntohost(hostname, &rarp46.a46_tha) == 0
		  || (rarp46.a46_tha.ea_addr[0] == 'v'
		    && (memcpy(&ip_addr, rarp46.a46_tha.ea_addr+2, 4), 1)
		    && (hostent= gethostbyaddr((char*) &ip_addr,
						4, AF_INET)) != NULL
		    && addhostname(hostname, hostent->h_name,
						rarp46.a46_tha.ea_addr[1])))
		&& (hostent= gethostbyname(hostname)) != NULL
		&& hostent->h_addrtype == AF_INET
	    ) {
		/* Host is found in the ethers file and the DNS, or the
		 * ethernet address denotes a special additional address
		 * used for implementing a TCP/IP stack in user space.
		 */
		for (i= 0; hostent->h_addr_list[i] != NULL; i++) {
		    memcpy(&ip_addr, hostent->h_addr_list[i], sizeof(ipaddr_t));

		    /* Check if the address is on this network. */
		    if (((ip_addr ^ ep->ip_addr) & ep->ip_mask) == 0) break;
		}

		if (hostent->h_addr_list[i] != NULL) {
		    rarp_reply(ep, hostname, ip_addr, rarp46.a46_tha);
		} else {
		    if (debug >= 2) {
			printf("%s: Host '%s' (%s) is on the wrong net\n",
			    ethdev(ep->n),
			    hostname, ether_ntoa(&rarp46.a46_tha));
		    }
		}
	    } else {
		if (debug >= 2) {
		    printf("%s: RARP request from unknown host '%s'\n",
			ethdev(ep->n), ether_ntoa(&rarp46.a46_tha));
		}
	    }
	}

	/* Wait for another request. */
	if (asyn_wait(&asyn, 0, NULL) < 0) {
	    report("asyn_wait()");
	    sleep(10);
	}
    }
}
Exemple #2
0
int main(int argc, char **argv)
{
	int i;
	struct servent *service;
	udpport_t route_port;
	nwio_udpopt_t udpopt;
	nwio_ipopt_t ipopt;
	asynchio_t asyn;
	time_t timeout;
	struct timeval tv;
	struct sigaction sa;
	char *offset_arg, *offset_end;
	long arg;

	udp_device= ip_device= nil;
	offset_arg= nil;

	for (i = 1; i < argc && argv[i][0] == '-'; i++) {
		char *p= argv[i] + 1;

		if (p[0] == '-' && p[1] == 0) { i++; break; }

		while (*p != 0) {
			switch (*p++) {
			case 'U':
				if (udp_device != nil) usage();
				if (*p == 0) {
					if (++i == argc) usage();
					p= argv[i];
				}
				udp_device= p;
				p= "";
				break;
			case 'I':
				if (ip_device != nil) usage();
				if (*p == 0) {
					if (++i == argc) usage();
					p= argv[i];
				}
				ip_device= p;
				p= "";
				break;
			case 'o':
				if (offset_arg != nil) usage();
				if (*p == 0) {
					if (++i == argc) usage();
					p= argv[i];
				}
				offset_arg= p;
				p= "";
				break;
			case 'b':
				bcast= 1;
				break;
			case 's':
				/*obsolete*/
				break;
			case 'd':
				debug= 1;
				break;
			default:
				usage();
			}
		}
	}
	if (i != argc) usage();

	/* Debug level signals. */
	sa.sa_handler= sig_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags= 0;
	sigaction(SIGUSR1, &sa, nil);
	sigaction(SIGUSR2, &sa, nil);

	if (udp_device == nil && (udp_device= getenv("UDP_DEVICE")) == nil)
		udp_device= UDP_DEVICE;

	if (ip_device == nil && (ip_device= getenv("IP_DEVICE")) == nil)
		ip_device= IP_DEVICE;

	if (offset_arg == nil) {
		priority_offset= PRIO_OFF_DEF;
	} else {
		arg= strtol(offset_arg, &offset_end, 0);
		if (*offset_end != 0 || (priority_offset= arg) != arg) usage();
	}

	if ((service= getservbyname("route", "udp")) == nil) {
		fprintf(stderr,
	"irdpd: unable to look up the port number for the 'route' service\n");
		exit(1);
	}

	route_port= (udpport_t) service->s_port;

	if ((rip_fd= open(udp_device, O_RDWR)) < 0) fatal(udp_device);

	udpopt.nwuo_flags= NWUO_COPY | NWUO_LP_SET | NWUO_DI_LOC
		| NWUO_EN_BROAD | NWUO_RP_SET | NWUO_RA_ANY | NWUO_RWDATALL
		| NWUO_DI_IPOPT;
	udpopt.nwuo_locport= route_port;
	udpopt.nwuo_remport= route_port;
	if (ioctl(rip_fd, NWIOSUDPOPT, &udpopt) < 0)
		fatal("setting UDP options failed");

	if ((irdp_fd= open(ip_device, O_RDWR)) < 0) fatal(ip_device);

	ipopt.nwio_flags= NWIO_COPY | NWIO_EN_LOC | NWIO_EN_BROAD
			| NWIO_REMANY | NWIO_PROTOSPEC
			| NWIO_HDR_O_SPEC | NWIO_RWDATALL;
	ipopt.nwio_tos= 0;
	ipopt.nwio_ttl= 1;
	ipopt.nwio_df= 0;
	ipopt.nwio_hdropt.iho_opt_siz= 0;
	ipopt.nwio_rem= htonl(0xFFFFFFFFL);
	ipopt.nwio_proto= IPPROTO_ICMP;

	if (ioctl(irdp_fd, NWIOSIPOPT, &ipopt) < 0)
		fatal("can't configure ICMP channel");

	asyn_init(&asyn);

	while (1) {
		ssize_t r;

		if (do_rip) {
			/* Try a RIP read. */
			r= asyn_read(&asyn, rip_fd, rip_buf, sizeof(rip_buf));
			if (r < 0) {
				if (errno == EIO) fatal(udp_device);
				if (errno != EINPROGRESS) report(udp_device);
			} else {
				now= time(nil);
				rip_incoming(r);
			}
		}

		if (do_rdisc) {
			/* Try an IRDP read. */
			r= asyn_read(&asyn, irdp_fd, irdp_buf,
							sizeof(irdp_buf));
			if (r < 0) {
				if (errno == EIO) fatal(ip_device);
				if (errno != EINPROGRESS) report(ip_device);
			} else {
				now= time(nil);
				irdp_incoming(r);
			}
		}
		fflush(stdout);

		/* Compute the next wakeup call. */
		timeout= next_sol < next_advert ? next_sol : next_advert;

		/* Wait for a RIP or IRDP packet or a timeout. */
		tv.tv_sec= timeout;
		tv.tv_usec= 0;
		if (asyn_wait(&asyn, 0, timeout == NEVER ? nil : &tv) < 0) {
			/* Timeout? */
			if (errno != EINTR && errno != EAGAIN)
				fatal("asyn_wait()");
			now= time(nil);
			time_functions();
		}
	}
}
Exemple #3
0
int asyn_close(asynchio_t *asyn, int fd)
{
	asyn_init(asyn);
}