bootp.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include "dat.h"
  5. #include "protos.h"
  6. enum
  7. {
  8. OfferTimeout= 60, /* when an offer times out */
  9. MaxLease= 60*60, /* longest lease for dynamic binding */
  10. MinLease= 15*60, /* shortest lease for dynamic binding */
  11. StaticLease= 30*60, /* lease for static binding */
  12. IPUDPHDRSIZE= 28, /* size of an IP plus UDP header */
  13. MINSUPPORTED= 576, /* biggest IP message the client must support */
  14. /* lengths of some bootp fields */
  15. Maxhwlen= 16,
  16. Maxfilelen= 128,
  17. Maxoptlen= 312-4,
  18. /* bootp types */
  19. Bootrequest= 1,
  20. Bootreply= 2,
  21. /* bootp flags */
  22. Fbroadcast= 1<<15,
  23. };
  24. typedef struct Hdr Hdr;
  25. struct Hdr
  26. {
  27. uchar op; /* opcode */
  28. uchar htype; /* hardware type */
  29. uchar hlen; /* hardware address len */
  30. uchar hops; /* hops */
  31. uchar xid[4]; /* a random number */
  32. uchar secs[2]; /* elapsed since client started booting */
  33. uchar flags[2];
  34. uchar ciaddr[IPv4addrlen]; /* client IP address (client tells server) */
  35. uchar yiaddr[IPv4addrlen]; /* client IP address (server tells client) */
  36. uchar siaddr[IPv4addrlen]; /* server IP address */
  37. uchar giaddr[IPv4addrlen]; /* gateway IP address */
  38. uchar chaddr[Maxhwlen]; /* client hardware address */
  39. char sname[64]; /* server host name (optional) */
  40. char file[Maxfilelen]; /* boot file name */
  41. uchar optmagic[4];
  42. uchar optdata[Maxoptlen];
  43. };
  44. enum
  45. {
  46. Oca,
  47. Osa,
  48. Ot,
  49. };
  50. static Field p_fields[] =
  51. {
  52. {"ca", Fv4ip, Oca, "client IP addr", } ,
  53. {"sa", Fv4ip, Osa, "server IP addr", } ,
  54. {0}
  55. };
  56. #define plan9opt ((ulong)(('p'<<24) | ('9'<<16) | (' '<<8) | ' '))
  57. #define genericopt (0x63825363UL)
  58. static Mux p_mux[] =
  59. {
  60. {"dhcp", genericopt,},
  61. {"plan9bootp", plan9opt,},
  62. {"dump", 0,},
  63. {0}
  64. };
  65. static void
  66. p_compile(Filter *f)
  67. {
  68. Mux *m;
  69. if(f->op == '='){
  70. compile_cmp(bootp.name, f, p_fields);
  71. return;
  72. }
  73. for(m = p_mux; m->name != nil; m++)
  74. if(strcmp(f->s, m->name) == 0){
  75. f->pr = m->pr;
  76. f->ulv = m->val;
  77. f->subop = Ot;
  78. return;
  79. }
  80. sysfatal("unknown bootp field: %s", f->s);
  81. }
  82. static int
  83. p_filter(Filter *f, Msg *m)
  84. {
  85. Hdr *h;
  86. h = (Hdr*)m->ps;
  87. if(m->pe < (uchar*)h->sname)
  88. return 0;
  89. m->ps = h->optdata;
  90. switch(f->subop){
  91. case Oca:
  92. return NetL(h->ciaddr) == f->ulv || NetL(h->yiaddr) == f->ulv;
  93. case Osa:
  94. return NetL(h->siaddr) == f->ulv;
  95. case Ot:
  96. return NetL(h->optmagic) == f->ulv;
  97. }
  98. return 0;
  99. }
  100. static char*
  101. op(int i)
  102. {
  103. static char x[20];
  104. switch(i){
  105. case Bootrequest:
  106. return "Req";
  107. case Bootreply:
  108. return "Rep";
  109. default:
  110. sprint(x, "%d", i);
  111. return x;
  112. }
  113. }
  114. static int
  115. p_seprint(Msg *m)
  116. {
  117. Hdr *h;
  118. ulong x;
  119. h = (Hdr*)m->ps;
  120. if(m->pe < (uchar*)h->sname)
  121. return -1;
  122. /* point past data */
  123. m->ps = h->optdata;
  124. /* next protocol */
  125. m->pr = nil;
  126. if(m->pe >= (uchar*)h->optdata){
  127. x = NetL(h->optmagic);
  128. demux(p_mux, x, x, m, &dump);
  129. }
  130. m->p = seprint(m->p, m->e, "t=%s ht=%d hl=%d hp=%d xid=%ux sec=%d fl=%4.4ux ca=%V ya=%V sa=%V ga=%V cha=%E magic=%lux",
  131. op(h->op), h->htype, h->hlen, h->hops,
  132. NetL(h->xid), NetS(h->secs), NetS(h->flags),
  133. h->ciaddr, h->yiaddr, h->siaddr, h->giaddr, h->chaddr,
  134. (ulong)NetL(h->optmagic));
  135. if(m->pe > (uchar*)h->sname && *h->sname)
  136. m->p = seprint(m->p, m->e, " snam=%s", h->sname);
  137. if(m->pe > (uchar*)h->file && *h->file)
  138. m->p = seprint(m->p, m->e, " file=%s", h->file);
  139. return 0;
  140. }
  141. Proto bootp =
  142. {
  143. "bootp",
  144. p_compile,
  145. p_filter,
  146. p_seprint,
  147. p_mux,
  148. "%#.8lux",
  149. p_fields,
  150. defaultframer,
  151. };