bootpcmd.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:16k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /*************************************************/
  2. /* Center for Information Technology Integration */
  3. /*           The University of Michigan          */
  4. /*                    Ann Arbor                  */
  5. /*                                               */
  6. /* Dedicated to the public domain.               */
  7. /* Send questions to info@citi.umich.edu         */
  8. /*                                               */
  9. /* BOOTP is documented in RFC 951 and RFC 1048   */
  10. /*************************************************/
  11. #include <stdio.h>
  12. #include <systypes.h>
  13. #include <sysstat.h>
  14. #include <time.h>
  15. #include <ctype.h>
  16. #include <stdarg.h>
  17. #include "global.h"
  18. #include "config.h"
  19. #include "cmdparse.h"
  20. #include "bootpd.h"
  21. #include "netuser.h"
  22. #include "iface.h"
  23. #include "udp.h"
  24. #include "arp.h"
  25. #define BP_DEFAULT_TAB "bootptab"
  26. #define BP_DEFAULT_LOG "bootplog"
  27. #define BP_DEFAULT_DIR "bpfiles"
  28. #define BP_DEFAULT_FILE "boot"
  29. static char    *bootptab = BP_DEFAULT_TAB;
  30. static FILE    *bootfp;                 /* bootptab fp */
  31. static long     modtime;           /* last modification time of bootptab */
  32. static char    bootplog[64] = BP_DEFAULT_LOG;
  33. static int LogInFile = 0;   /* Should bp_log log in a file? */
  34. static int LogOnScreen = 0; /* Should bp_log log on screen? */
  35. static char    *line;            /* line buffer for reading bootptab */
  36. static int     linenum;          /* current ilne number in bootptab */
  37. extern int Nhosts;          /* number of hosts in host structure */
  38. extern struct host hosts[MHOSTS];
  39. extern char    homedir[64];      /* bootfile homedirectory */
  40. extern char    defaultboot[64];  /* default file to boot */
  41. extern int32   bp_DefaultDomainNS[BP_MAXDNS]; /* default domain name server */
  42. extern int Nhosts;
  43. extern struct udp_cb *Bootpd_cb;
  44. static int bp_Homedir(int argc,char *argv[],void *p);
  45. static int bp_DefaultFile(int argc,char *argv[],void *p);
  46. static int bp_DynamicRange(int argc,char *argv[],void *p);
  47. static int bp_donothing(int argc,char *argv[],void *p);
  48. static int bp_Host(int argc,char *argv[],void *p);
  49. static int bp_rmHost(int argc,char *argv[],void *p);
  50. static int bp_DomainNS(int argc,char *argv[],void *p);
  51. static int bp_Start(int argc,char *argv[],void *p);
  52. static int bp_Stop(int argc,char *argv[],void *p);
  53. static int bp_logFile(int argc,char *argv[],void *p);
  54. static int bp_logScreen(int argc,char *argv[],void *p);
  55. static void dumphosts(void);
  56. void bootpd(struct iface *iface, struct udp_cb *sock, int cnt);
  57. static struct cmds BootpdCmds[] = {
  58.         "",             bp_donothing,           0, 0, NULL,
  59. "start",  bp_Start, 0, 0, NULL,
  60. "stop", bp_Stop, 0, 0, NULL,
  61. "dns", bp_DomainNS, 0, 0, NULL,
  62.         "dynip",     bp_DynamicRange,      0, 0, NULL,
  63. "host", bp_Host, 0, 0, NULL,
  64. "rmhost", bp_rmHost, 0, 0, NULL,
  65.         "homedir",      bp_Homedir,           0, 0, NULL,
  66.         "defaultfile",  bp_DefaultFile,       0, 0, NULL,
  67. "logfile", bp_logFile, 0, 0, NULL,
  68. "logscreen", bp_logScreen, 0, 0, NULL,
  69.         NULL,       NULL,                 0, 0, NULL
  70. };
  71. int 
  72. bootpdcmd (argc, argv, p)
  73. int argc;
  74. char *argv[];
  75. void *p;
  76. {
  77. return subcmd (BootpdCmds, argc, argv, p);
  78. }
  79. /* Start up bootp service */
  80. static int
  81. bp_Start (argc,argv,p)
  82. int argc;
  83. char *argv[];
  84. void *p;
  85. {
  86.         struct socket lsock;
  87.         time_t tloc;
  88. char *usage = "bootpd startn";
  89. if (argc != 1) {
  90. printf (usage);
  91. return (-1);
  92. }
  93. time(&tloc);
  94.         bp_log ("nn####BOOTP server starting at %sn", ctime(&tloc));
  95.         lsock.address = INADDR_ANY;
  96.         lsock.port = IPPORT_BOOTPS;
  97.         /* This way is better than recvfrom because it passes the iface in bootpd call */
  98.        /* Listen doesn't work for datagrams. */
  99.         if (Bootpd_cb == NULL) {
  100.                 if ((Bootpd_cb = open_udp(&lsock, bootpd)) == NULL) {
  101. printf ("bootpd: can't open_udpn");
  102. return (-1);
  103. }
  104.         }
  105.         /*
  106.          * Read the bootptab file once immediately upon startup.
  107.          */
  108.         da_init();
  109.         readtab();
  110.         return (0);
  111. }
  112. /* Stop bootp service */
  113. static int
  114. bp_Stop (argc, argv, p)
  115. int argc;
  116. char *argv[];
  117. void *p;
  118. {
  119. time_t now;
  120. char *usage = "bootpd stopn";
  121. if (argc != 1) {
  122. printf (usage);
  123. return -1;
  124. }
  125. time (&now);
  126.         Nhosts = 0;
  127.         da_shut();
  128.         readtab_shut();
  129.         del_udp (Bootpd_cb);
  130.         Bootpd_cb = NULL;
  131. bp_log ("Bootpd shutdown %s", ctime (&now));
  132.         return (0);
  133. };
  134. static int
  135. bp_logFile (argc, argv, p)
  136. int argc;
  137. char *argv[];
  138. void *p;
  139. {
  140. int i;
  141. time_t now;
  142. char *usage = "bootpd logfile [<file_name> | default] [on | off] n"; 
  143. time (&now);
  144. if (argc == 1) {
  145. if (LogInFile)
  146.                  printf ("Bootpd logging to file '%s' turned on.n", bootplog);
  147. else 
  148.                  printf ("Bootpd logging to file '%s' turned off.n", bootplog);
  149. }
  150. else {
  151. for (i = 1; i < argc; i++) {
  152. if (strcmp ("?", argv[i]) == 0) 
  153. printf (usage);
  154. else if (strcmp ("off", argv[i]) == 0) {
  155. bp_log ("Stopping file logging at %s", ctime(&now));
  156. LogInFile = 0;
  157. }
  158. else if (strcmp ("on", argv[i]) == 0) {
  159. LogInFile = 1;
  160. bp_log ("Starting file logging at %s", ctime(&now));
  161. }
  162. else if (strcmp ("default", argv[i]) == 0) {
  163. strcpy (bootplog, BP_DEFAULT_LOG);
  164. bp_log ("File for logging set to %sn", bootplog);
  165. }
  166. else {
  167. strcpy (bootplog, argv[1]);
  168. bp_log ("File for logging set to %sn", bootplog);
  169. }
  170. }
  171. }
  172. return 0;
  173. }
  174. static int
  175. bp_logScreen (argc, argv, p)
  176. int argc;
  177. char *argv[];
  178. void *p;
  179. {
  180. char *usage = "bootpd logscreen [on | off]n";
  181.         if (argc == 1)
  182. if (LogOnScreen)
  183.                  printf ("Bootpd logging on screen turned on.n");
  184. else 
  185.                  printf ("Bootpd logging on screen turned off.n");
  186.         else if (argc == 2)  {
  187.                 if  (strcmp ("on", argv[1]) == 0)
  188.                         LogOnScreen = 1;
  189.                 else if  (strcmp ("off", argv[1]) == 0)
  190.                         LogOnScreen = 0;
  191. else printf (usage);
  192. }
  193. else printf (usage);
  194. return 0;
  195. }
  196. static int
  197. bp_DomainNS (argc, argv, p)
  198. int argc;
  199. char *argv[];
  200. void *p;
  201. {
  202. int a0, a1, a2, a3;
  203. int i;
  204. char *usage = "bootpd dns [<IP addr of domain name server>...]n";
  205. if (argc == 1) {
  206. printf ("Bootp domain name servers: ");
  207. for (i=0; (i < BP_MAXDNS) && (bp_DefaultDomainNS[i] != 0); i++) 
  208. printf (" %s", inet_ntoa (bp_DefaultDomainNS[i]));
  209. printf ("n");
  210. return (0);
  211. }
  212. if (argc > 1) {
  213. if ((argc == 2) && (strcmp ("?", argv[1]) == 0)) {
  214. printf (usage);
  215. return 0;
  216. }
  217. /* A list of name servers has been given */
  218. /* reset the domain name server list */
  219. for (i= 0; i < BP_MAXDNS; i++) 
  220. bp_DefaultDomainNS[i] = 0;
  221. /* get ip address */
  222. for (i = 1; (i < argc) && (i < BP_MAXDNS); i++) {
  223.                  if (4 != sscanf (argv[i], "%d.%d.%d.%d", &a0, &a1, &a2, &a3)) {
  224.                           printf("bad internet address: %sn", argv[1], linenum);
  225. return  -1;
  226.                  }
  227.          bp_DefaultDomainNS[i-1] = aton(argv[i]);
  228. }
  229. }
  230. /* record for the loggers sake */
  231. bp_log ("Bootp domain name servers: ");
  232. for (i=0; (i < BP_MAXDNS) && (bp_DefaultDomainNS[i] != 0); i++) 
  233. bp_log (" %s", inet_ntoa (bp_DefaultDomainNS[i]));
  234. bp_log ("n");
  235. return 0;
  236. }
  237. static int
  238. bp_rmHost (argc, argv, p)
  239. int argc;
  240. char *argv[];
  241. void *p;
  242. {
  243. int i;
  244. struct host *hp = NULL;
  245. struct host *cp = NULL;
  246. char *usage = "bootpd rmhost <host name>n";
  247. if (argc == 2) {
  248. /* Find the host record */
  249. for (i=0; i < Nhosts; i++) {
  250. if (strcmp (hosts[i].name, argv[1]) == 0) {
  251. hp = &(hosts[i]);
  252. break;
  253. }
  254. }
  255. /* Return if not found */
  256. if (hp == NULL) {
  257. printf ("Host %s not in host tables.n", argv[1]);
  258. return -1;
  259. }
  260. bp_log ("Host %s removed from host tablen", hp->name);
  261. cp = &(hosts [Nhosts - 1]);
  262. if (hp < cp) 
  263. memcpy(hp,cp,sizeof(struct host));
  264. Nhosts--;
  265. return 0;
  266. }
  267. else printf (usage);
  268. return 0;
  269. }
  270. /*
  271.  * Printout the hosts table.
  272. */
  273. static void
  274. dumphosts()
  275. {
  276.         int i;
  277.         struct host *hp;
  278. struct arp_type *at;
  279.         printf ("nnStatus of host tablen");
  280.         if (Nhosts == 0) {
  281.                 printf ("     No hosts in host tablen");
  282.                 return;
  283.         }
  284.         for (i = 0; i <= Nhosts-1; i++) {
  285.                 hp = &hosts[i];
  286. at = &Arp_type[hp->htype];
  287.                 printf ("%s  %s  %s  %s  '%s'n",
  288.                         hp->name, ArpNames[hp->htype], (*at->format)(bp_ascii, hp->haddr),
  289.                         inet_ntoa ((int32)hp->iaddr.s_addr),
  290.                         hp->bootfile);
  291.         }
  292. }
  293. static int
  294. bp_Host (argc, argv, p)
  295. int argc;
  296. char *argv[];
  297. void *p;
  298. {
  299. struct host *hp;
  300. int a0, a1, a2, a3;
  301. struct arp_type *at;
  302. char *usage = "bootpd host [<hostname> <hardware type> <hardware addr> <ip addr> [boot file]]n";
  303. switch (argc) {
  304. case 1:
  305. dumphosts();
  306. break;
  307. case 5:
  308. case 6:
  309. hp = &hosts[Nhosts];
  310. /* get host name */
  311. strncpy (hp->name, argv[1], sizeof (hp->name));
  312. /* get hardware type */
  313. /* This code borrowed from Phil Karn's arpcmd.c */
  314. /* This is a kludge. It really ought to be table driven */
  315. switch(tolower(argv[2][0])){
  316. case 'n':       /* Net/Rom pseudo-type */
  317. hp->htype = ARP_NETROM;
  318. break;
  319. case 'e': /* "ether" */
  320. hp->htype = ARP_ETHER;
  321. break;
  322. case 'a': /* "ax25" */
  323. hp->htype = ARP_AX25;
  324. break;
  325. case 'm': /* "mac appletalk" */
  326. hp->htype = ARP_APPLETALK;
  327. break;
  328. default:
  329. printf("unknown hardware type "%s"n",argv[2]);
  330. return -1;
  331. }
  332. at = &Arp_type[hp->htype];
  333. if(at->scan == NULL){
  334. return 1;
  335. }
  336. /* Destination address */
  337. (*at->scan)(hp->haddr,argv[3]);
  338. /* get ip address */
  339.                 if (4 != sscanf (argv[4], "%d.%d.%d.%d", &a0, &a1, &a2, &a3))
  340.                 {
  341.                         printf("bad internet address: %sn", argv[1], linenum);
  342.                         return (0);
  343.                 }
  344.         hp->iaddr.s_addr = aton(argv[4]);
  345. /* get the bootpfile */
  346. if (argc == 6) strncpy (hp->bootfile, argv[5], sizeof (hp->bootfile));
  347. else hp->bootfile[0] = 0;
  348.                 bp_log ("Host added: %s  %s  %s  %s  '%s'n",
  349.                         hp->name, ArpNames[hp->htype], (*at->format)(bp_ascii, hp->haddr),
  350.                         inet_ntoa ((int32)hp->iaddr.s_addr),
  351.                         hp->bootfile);
  352. Nhosts++;
  353. break;
  354. default:
  355. printf (usage);
  356. break;
  357. }
  358. return 0;
  359. }
  360. static int
  361. bp_Homedir (argc, argv, p)
  362. int argc;
  363. char *argv[];
  364. void *p;
  365. {
  366. char *usage = "bootpd homedir [<name of home directory> | default]n";
  367. if (argc == 1) 
  368. printf ("Bootp home directory: '%s'n", homedir);
  369. else if (argc == 2) {
  370. if (strcmp (argv[1], "?") == 0)
  371. printf (usage);
  372. else if (strcmp (argv[1], "default") == 0) {
  373. strcpy (homedir, BP_DEFAULT_DIR);
  374. bp_log ("Bootp home directory set to: '%s'n", homedir);
  375. }
  376. else {
  377. strcpy (homedir, argv[1]);
  378. bp_log ("Bootp home directory set to: '%s'n", homedir);
  379. }
  380. }
  381. else printf (usage);
  382. return (0);
  383. };
  384. static int
  385. bp_DefaultFile (argc, argv, p)
  386. int argc;
  387. char *argv[];
  388. void *p;
  389. {
  390. char *usage = "bootpd defaultfile [<name of default boot file> | default]n";
  391.         if (argc == 1)
  392.                 printf ("Bootp default boot file:  '%s'n", defaultboot);
  393.         else if (argc == 2) {
  394. if (strcmp (argv[1], "?") == 0)
  395.                         printf (usage);
  396.                 else if (strcmp (argv[1], "default") == 0)
  397.                         strcpy (defaultboot, BP_DEFAULT_FILE);
  398.                 else {
  399.                         strcpy (defaultboot, argv[1]);
  400.                  bp_log ("Bootp default boot file set to:  '%s'n", defaultboot);
  401. }
  402.         }
  403. else
  404.                 printf (usage);
  405. return  (0);
  406. };
  407. static int
  408. bp_DynamicRange (argc, argv, p)
  409. int argc;
  410. char *argv[];
  411. void *p;
  412. {
  413. int i0, i1, i2, i3;
  414. int32 start, end;
  415. struct iface *iface;
  416. char *usage = "bootpd dynip [<net name> | <netname>  <IP address> <IP address> | <netname> off]n";
  417. if (argc == 1) {
  418. da_status (NULL);
  419. return 0;
  420. }
  421. if ((argc == 2) && (strcmp ("?", argv[1]) == 0)) {
  422. printf (usage);
  423. return 0;
  424. }
  425. /* get the interface */
  426. iface = if_lookup (argv[1]);
  427. if (iface == NULL) {
  428. printf ("network '%s' not foundn", argv[1]);
  429. return  (-1);
  430. }
  431. if (argc == 2) {
  432. da_status (iface);
  433. return 0;
  434. }
  435. if (argc == 3) {
  436. if (strcmp ("off", argv[2]) == 0) 
  437. da_done_net (iface);
  438. else printf (usage);
  439. }
  440. else if (argc == 4) {
  441.         /* get ip address */
  442.                 /* check the ip address - isaddr isn't a ka9q function */
  443.                 if ((4 != sscanf (argv[2], "%d.%d.%d.%d", &i0, &i1, &i2, &i3)) || 
  444. (i0 > 255) || (i1 > 255) || (i2 > 255) || (i3 > 255)
  445. )
  446.                 {
  447.                  printf("bad internet address: %sn", argv[2], linenum);
  448.                         return (-1);
  449.                 }
  450.                 if ((4 != sscanf (argv[3], "%d.%d.%d.%d", &i0, &i1, &i2, &i3)) || 
  451. (i0 > 255) || (i1 > 255) || (i2 > 255) || (i3 > 255)
  452. )
  453.                 {
  454.                  printf("bad internet address: %sn", argv[3], linenum);
  455.                         return (-1);
  456.                 }
  457.                 start = aton(argv[2]);
  458.              end = aton(argv[3]);
  459. da_serve_net (iface, start, end);
  460. }
  461. else {
  462. printf (usage);
  463. return (0);
  464. }
  465. return (0);
  466. };
  467. static int
  468. bp_donothing (argc, argv, p)
  469. int argc;
  470. char *argv[];
  471. void *p;
  472. {
  473.         return (0);
  474. }
  475. /*
  476.  * Read bootptab database file.  Avoid rereading the file if the
  477.  * write date hasn't changed since the last time we read it.
  478.  */
  479. int
  480. readtab()
  481. {
  482.         struct stat st;
  483.         /* If the file hasn't been opened, open it. */
  484.         if (bootfp == 0) {
  485.                 if ((bootfp = fopen(bootptab, "r")) == NULL) {
  486.                         bp_log("Can't open bootptab file: %sn", bootptab);
  487.                         return (-1);
  488.                 }
  489.         }
  490.         /* Only reread if modified */
  491.         stat (bootptab, &st);
  492.         if (st.st_mtime == modtime && st.st_nlink) {
  493.                 return (0); /* hasnt been modified or deleted yet */
  494.         }
  495.         /* It's been changed, reread. */
  496.         if ((bootfp = fopen(bootptab, "r")) == NULL) {
  497.                 bp_log("Can't open %sn", bootptab);
  498.                 return (-1);
  499.         }
  500.         fstat(fileno(bootfp), &st);
  501.         bp_log("(re)reading %sn", bootptab);
  502.         modtime = st.st_mtime;
  503.         /*
  504.          * read and parse each line in the file.
  505.          */
  506. line = mallocw(BUFSIZ);
  507. while (fgets(line, BUFSIZ, bootfp) != NULL) {
  508. linenum++;
  509. if ((line[0] == 0) || (line[0] == '#') || (line[0] == ' '))
  510. continue;
  511.                 if (cmdparse (BootpdCmds, line, NULL) ==  -1)
  512.                          continue;
  513.         }
  514.         fclose(bootfp);
  515. free (line);
  516. return (0);
  517. }
  518. void
  519. readtab_shut()
  520. {
  521. modtime = 0;
  522. }
  523. /*
  524.  * log an error message
  525.  *
  526.  */
  527. void
  528. bp_log(char *fmt,...)
  529. {
  530.         FILE *fp;
  531. va_list ap;
  532.         if (LogOnScreen) {
  533. va_start(ap,fmt);
  534. vprintf(fmt, ap);
  535. va_end(ap);
  536. fflush (stdout);
  537. }
  538.         if (LogInFile) {
  539.                 if ((fp = fopen(bootplog, "a+")) == NULL) {
  540.                         printf ("Cannot open bootplog.n");
  541.                         return;
  542.                 }
  543. va_start(ap,fmt);
  544. vfprintf(fp, fmt, ap);
  545. va_end(ap);
  546.                 fflush(fp);
  547.                 fclose(fp);
  548.         }
  549. }