bootp.c 3.8 KB

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