Ejemplo n.º 1
0
bool
bootpc_init(bool update_files, bool forever)
{
  struct bootp_packet call;
  struct bootp_packet reply;
  static u_int32_t xid = ~0xFF;
  
  struct ifreq ireq;
  struct ifnet *ifp;
  struct socket *so;
  int j;
  int error;
  struct sockaddr_in myaddr;
  struct ifaddr *ifa;
  struct sockaddr_dl *sdl = NULL;
  char *delim;
  struct proc *procp = NULL;

  /*
   * If already filled in, don't touch it here 
   */
  if (nfs_diskless_valid)
    return true;

  /*
   * If we are to update the files create the root
   * file structure.
   */
  if (update_files)
    if (rtems_create_root_fs () < 0) {
      printf("Error creating the root filesystem.\nFile not created.\n");
      update_files = 0;
    }

  if (dhcp_hostname != NULL) {
	/* free it */
    dhcp_hostname=bootp_strdup_realloc(dhcp_hostname,0);
  }

  /*
   * Find a network interface.
   */
  for (ifp = ifnet; ifp != 0; ifp = ifp->if_next)
    if ((ifp->if_flags &
      (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
	break;
  if (ifp == NULL) {
    printf("bootpc_init: no suitable interface\n");
    return false;
  }
  bzero(&ireq,sizeof(ireq));
  sprintf(ireq.ifr_name, "%s%d", ifp->if_name,ifp->if_unit);
  printf("bootpc_init: using network interface '%s'\n",
	 ireq.ifr_name);

  if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0) {
    printf("bootpc_init: socreate, error=%d", error);
    return false;
  }
  if (bootpc_fakeup_interface(&ireq,so,procp) != 0) {
    soclose(so);
    return false;
  }

  /* Get HW address */

  for (ifa = ifp->if_addrlist;ifa; ifa = ifa->ifa_next)
    if (ifa->ifa_addr->sa_family == AF_LINK &&
        (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) &&
        sdl->sdl_type == IFT_ETHER)
      break;
  
  if (!sdl) {
    printf("bootpc: Unable to find HW address\n");
    soclose(so);
    return false;
  }
  if (sdl->sdl_alen != EALEN ) {
    printf("bootpc: HW address len is %d, expected value is %d\n",
	   sdl->sdl_alen,EALEN);
    soclose(so);
    return false;
  }

  printf("bootpc hw address is ");
  delim="";
  for (j=0;j<sdl->sdl_alen;j++) {
    printf("%s%x",delim,((unsigned char *)LLADDR(sdl))[j]);
    delim=":";
  }
  printf("\n");

#if 0
  bootpboot_p_iflist();
  bootpboot_p_rtlist();
#endif

  while (true) {
    bzero((caddr_t) &call, sizeof(call));

    /* bootpc part */
    call.op = 1; 			/* BOOTREQUEST */
    call.htype= 1;		/* 10mb ethernet */
    call.hlen=sdl->sdl_alen;	/* Hardware address length */
    call.hops=0;	
    xid++;
    call.xid = txdr_unsigned(xid);
    bcopy(LLADDR(sdl),&call.chaddr,sdl->sdl_alen);
  
    call.vend[0]=99;
    call.vend[1]=130;
    call.vend[2]=83;
    call.vend[3]=99;
    call.vend[4]=255;
  
    call.secs = 0;
    call.flags = htons(0x8000); /* We need an broadcast answer */
  
    error = bootpc_call(&call,&reply,procp);
  
    if (!error)
      break;
    
    printf("BOOTP call failed -- error %d", error);

    if (!forever) {
      soclose(so);
      return false;
    }
  }
  
  /*
   * Initialize network address structures
   */
  bzero(&myaddr,sizeof(myaddr));
  bzero(&dhcp_netmask,sizeof(dhcp_netmask));
  bzero(&dhcp_gw,sizeof(dhcp_gw));
  myaddr.sin_len = sizeof(myaddr);
  myaddr.sin_family = AF_INET;
  dhcp_netmask.sin_len = sizeof(dhcp_netmask);
  dhcp_netmask.sin_family = AF_INET;
  dhcp_gw.sin_len = sizeof(dhcp_gw);
  dhcp_gw.sin_family= AF_INET;

  /*
   * Set our address
   */
  myaddr.sin_addr = reply.yiaddr;
  printip("My ip address",myaddr.sin_addr);

  /*
   * Process BOOTP/DHCP options
   */
  if (reply.vend[0]==99 && reply.vend[1]==130 &&
      reply.vend[2]==83 && reply.vend[3]==99) {
    processOptions (&reply.vend[4], sizeof(reply.vend) - 4);
  }
  if (dhcpOptionOverload & 1) {
    processOptions ((unsigned char *)reply.file, sizeof reply.file);
  }
  else {
    if (reply.file[0])
      rtems_bsdnet_bootp_boot_file_name = 
	bootp_strdup_realloc(rtems_bsdnet_bootp_boot_file_name,reply.file);
  }
  if (dhcpOptionOverload & 2) {
    processOptions ((unsigned char *)reply.sname, sizeof reply.sname);
  }
  else {
    if (reply.sname[0])
      rtems_bsdnet_bootp_server_name = 
	bootp_strdup_realloc(rtems_bsdnet_bootp_server_name,reply.sname);
  }
  if (rtems_bsdnet_bootp_server_name)
    printf ("Server name is %s\n", rtems_bsdnet_bootp_server_name);
  if (rtems_bsdnet_bootp_boot_file_name)
    printf ("Boot file is %s\n", rtems_bsdnet_bootp_boot_file_name);
  if (rtems_bsdnet_bootp_cmdline)
    printf ("Command line is %s\n", rtems_bsdnet_bootp_cmdline);

  /*
   * Use defaults if values were not supplied by BOOTP/DHCP options
   */
  if (!dhcp_gotnetmask) {
    if (IN_CLASSA(ntohl(myaddr.sin_addr.s_addr)))
      dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
    else if (IN_CLASSB(ntohl(myaddr.sin_addr.s_addr)))
      dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET);
    else 
      dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
  }
  printip ("Subnet mask", dhcp_netmask.sin_addr);
  if (!dhcp_gotserver)
   rtems_bsdnet_bootp_server_address = reply.siaddr;
  printip ("Server ip address" ,rtems_bsdnet_bootp_server_address);
  if (!dhcp_gotgw)
    dhcp_gw.sin_addr = reply.giaddr;
  printip ("Gateway ip address", dhcp_gw.sin_addr);
  if (!dhcp_gotlogserver)
    rtems_bsdnet_log_host_address = rtems_bsdnet_bootp_server_address;
  printip ("Log server ip address", rtems_bsdnet_log_host_address);

  /*
   * Update the files if we are asked too.
   */
  if (update_files) {
    char *dn = rtems_bsdnet_domain_name;
    char *hn = dhcp_hostname;
    if (!dn)
      dn = "mydomain";
    if (!hn)
      hn = "me";
    rtems_rootfs_append_host_rec(myaddr.sin_addr.s_addr, hn, dn);

    /*
     * Should the given domainname be used here ?
     */
    if (dhcp_gotserver) {
      if (rtems_bsdnet_bootp_server_name)
        hn = rtems_bsdnet_bootp_server_name;
      else
        hn = "bootps";
      rtems_rootfs_append_host_rec(rtems_bsdnet_bootp_server_address.s_addr,
                                   hn, dn);
    }

    if (dhcp_gotlogserver) {
      rtems_rootfs_append_host_rec(rtems_bsdnet_log_host_address.s_addr,
                                   "logs", dn);
    }

    /*
     * Setup the DNS configuration file /etc/resolv.conf.
     */
    if (rtems_bsdnet_nameserver_count) {
      int        i;
      char       buf[64];
      const char *bufl[1];

      bufl[0] = buf;
      
#define MKFILE_MODE (S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH)
      
      if (rtems_bsdnet_domain_name &&
          (strlen(rtems_bsdnet_domain_name) < (sizeof(buf) - 1))) {
        strcpy(buf, "search ");
        strcat(buf, rtems_bsdnet_domain_name);
        strcat(buf, "\n");
        rtems_rootfs_file_append ("/etc/resolv.conf", MKFILE_MODE, 1, bufl);
      }

      for (i = 0; i < rtems_bsdnet_nameserver_count; i++) {
        strcpy(buf, "nameserver ");
        strcat(buf, inet_ntoa(rtems_bsdnet_nameserver[i]));
        strcat(buf, "\n");
        if (rtems_rootfs_file_append ("/etc/resolv.conf", MKFILE_MODE, 1, bufl))
          break;
      }
    }
  }

  /*
   * Configure the interface with the new settings
   */
  error = bootpc_adjust_interface(&ireq,so,
				  &myaddr,&dhcp_netmask,&dhcp_gw,procp);
  soclose(so);

  return true;
}
Ejemplo n.º 2
0
void
bootpc_init(void)
{
	struct bootpc_ifcontext *ifctx, *nctx;	/* Interface BOOTP contexts */
	struct bootpc_globalcontext *gctx; 	/* Global BOOTP context */
	struct ifnet *ifp;
	int error;
#ifndef BOOTP_WIRED_TO
	int ifcnt;
#endif
	struct nfsv3_diskless *nd;
	struct thread *td;

	nd = &nfsv3_diskless;
	td = curthread;

	/*
	 * If already filled in, don't touch it here
	 */
	if (nfs_diskless_valid != 0)
		return;

	gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO);
	if (gctx == NULL)
		panic("Failed to allocate bootp global context structure");

	gctx->xid = ~0xFFFF;
	gctx->starttime = time_second;

	/*
	 * Find a network interface.
	 */
	CURVNET_SET(TD_TO_VNET(td));
#ifdef BOOTP_WIRED_TO
	printf("bootpc_init: wired to interface '%s'\n",
	       __XSTRING(BOOTP_WIRED_TO));
	allocifctx(gctx);
#else
	/*
	 * Preallocate interface context storage, if another interface
	 * attaches and wins the race, it won't be eligible for bootp.
	 */
	IFNET_RLOCK();
	for (ifp = TAILQ_FIRST(&V_ifnet), ifcnt = 0;
	     ifp != NULL;
	     ifp = TAILQ_NEXT(ifp, if_link)) {
		if ((ifp->if_flags &
		     (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
		    IFF_BROADCAST)
			continue;
		ifcnt++;
	}
	IFNET_RUNLOCK();
	if (ifcnt == 0)
		panic("bootpc_init: no eligible interfaces");
	for (; ifcnt > 0; ifcnt--)
		allocifctx(gctx);
#endif

	IFNET_RLOCK();
	for (ifp = TAILQ_FIRST(&V_ifnet), ifctx = gctx->interfaces;
	     ifp != NULL && ifctx != NULL;
	     ifp = TAILQ_NEXT(ifp, if_link)) {
		strlcpy(ifctx->ireq.ifr_name, ifp->if_xname,
		    sizeof(ifctx->ireq.ifr_name));
#ifdef BOOTP_WIRED_TO
		if (strcmp(ifctx->ireq.ifr_name,
			   __XSTRING(BOOTP_WIRED_TO)) != 0)
			continue;
#else
		if ((ifp->if_flags &
		     (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
		    IFF_BROADCAST)
			continue;
#endif
		ifctx->ifp = ifp;
		ifctx = ifctx->next;
	}
	IFNET_RUNLOCK();
	CURVNET_RESTORE();

	if (gctx->interfaces == NULL || gctx->interfaces->ifp == NULL) {
#ifdef BOOTP_WIRED_TO
		panic("bootpc_init: Could not find interface specified "
		      "by BOOTP_WIRED_TO: "
		      __XSTRING(BOOTP_WIRED_TO));
#else
		panic("bootpc_init: no suitable interface");
#endif
	}

	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
		bootpc_fakeup_interface(ifctx, gctx, td);

	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
		bootpc_compose_query(ifctx, gctx, td);

	error = bootpc_call(gctx, td);

	if (error != 0) {
#ifdef BOOTP_NFSROOT
		panic("BOOTP call failed");
#else
		printf("BOOTP call failed\n");
#endif
	}

	rootdevnames[0] = "nfs:";
#ifdef NFSCLIENT
	rootdevnames[1] = "oldnfs:";
#endif
	mountopts(&nd->root_args, NULL);

	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
		if (bootpc_ifctx_isresolved(ifctx) != 0)
			bootpc_decode_reply(nd, ifctx, gctx);

#ifdef BOOTP_NFSROOT
	if (gctx->gotrootpath == 0)
		panic("bootpc: No root path offered");
#endif

	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
		bootpc_adjust_interface(ifctx, gctx, td);

		soclose(ifctx->so);
	}

	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
		if (ifctx->gotrootpath != 0)
			break;
	if (ifctx == NULL) {
		for (ifctx = gctx->interfaces;
		     ifctx != NULL;
		     ifctx = ifctx->next)
			if (bootpc_ifctx_isresolved(ifctx) != 0)
				break;
	}
	if (ifctx == NULL)
		goto out;

	if (gctx->gotrootpath != 0) {

		setenv("boot.netif.name", ifctx->ifp->if_xname);

		error = md_mount(&nd->root_saddr, nd->root_hostnam,
				 nd->root_fh, &nd->root_fhsize,
				 &nd->root_args, td);
		if (error != 0)
			panic("nfs_boot: mountd root, error=%d", error);

		nfs_diskless_valid = 3;
	}

	strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name);
	bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr));
	bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr));
	((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr =
		ifctx->myaddr.sin_addr.s_addr |
		~ ifctx->netmask.sin_addr.s_addr;
	bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask));

out:
	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) {
		nctx = ifctx->next;
		free(ifctx, M_TEMP);
	}
	free(gctx, M_TEMP);
}