RedFlyNBNS.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include <inttypes.h>
  2. #if defined(__AVR__)
  3. # include <avr/pgmspace.h>
  4. #endif
  5. #if ARDUINO >= 100
  6. # include "Arduino.h"
  7. #else
  8. # include "WProgram.h"
  9. #endif
  10. #include "RedFly.h"
  11. #include "RedFlyNBNS.h"
  12. //NBNS Question
  13. #define NBNSQ_PACKETLEN (38)
  14. #define NBNSQ_TYPE_NB (0x0020)
  15. #define NBNSQ_CLASS_IN (0x0001)
  16. typedef struct __attribute__((packed))
  17. {
  18. uint8_t len : 8; // 8bit Len: 32
  19. char name[33]; //33byte Name + null
  20. uint16_t type : 16; //16bit Type
  21. uint16_t clas : 16; //16bit Class
  22. } NBNS_Question;
  23. //NBNS Answer
  24. #define NBNSA_PACKETLEN (50)
  25. #define NBNSA_TYPE_NB (0x0020)
  26. #define NBNSA_CLASS_IN (0x0001)
  27. typedef struct __attribute__((packed))
  28. {
  29. uint8_t len : 8; // 8bit Len: 32
  30. char name[33]; //33byte Name + null
  31. uint16_t type : 16; //16bit Type
  32. uint16_t clas : 16; //16bit Class
  33. uint32_t ttl : 32; //32bit Time to live
  34. uint16_t rdlen : 16; //16bit Data len
  35. uint16_t flags : 16; //16bit Flags - rdata
  36. uint8_t addr[4]; //32bit IP Addr - rdata
  37. } NBNS_Answer;
  38. //NBNS (NetBIOS Name Service)
  39. #define NBNS_PORT (137)
  40. #define NBNS_PACKETLEN (12)
  41. #define NBNS_OPMASK (0x7800)
  42. #define NBNS_REPLYMASK (0x000F)
  43. #define NBNS_FLAG_RESPONSE (1<<15)
  44. #define NBNS_FLAG_QUERY (0<<15)
  45. #define NBNS_FLAG_AUTHORITY (1<<10)
  46. #define NBNS_OP_QUERY (0<<11)
  47. typedef struct __attribute__((packed))
  48. {
  49. uint16_t id : 16; //16bit Transaction ID
  50. uint16_t flags_op : 16; //16bit Flags
  51. uint16_t qdcount : 16; //16bit Question Entries
  52. uint16_t ancount : 16; //16bit Answer RRs
  53. uint16_t nscount : 16; //16bit Authority RRs
  54. uint16_t arcount : 16; //16bit Additional RRs
  55. union
  56. {
  57. NBNS_Question qd;
  58. NBNS_Answer an;
  59. } data;
  60. } NBNS_Packet;
  61. //-------------------- Constructor/Destructor --------------------
  62. RedFlyNBNS::RedFlyNBNS(void) : RedFlyServer(NBNS_PORT)
  63. {
  64. strcpy(devname, "REDFLY");
  65. return;
  66. }
  67. RedFlyNBNS::RedFlyNBNS(char *name) : RedFlyServer(NBNS_PORT)
  68. {
  69. strcpy(devname, name);
  70. return;
  71. }
  72. RedFlyNBNS::~RedFlyNBNS(void)
  73. {
  74. stop();
  75. return;
  76. }
  77. //-------------------- Public --------------------
  78. void RedFlyNBNS::setName(char *name)
  79. {
  80. strcpy(devname, name);
  81. return;
  82. }
  83. #if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
  84. void RedFlyNBNS::setNamePGM(PGM_P name)
  85. {
  86. strcpy_P(devname, name);
  87. return;
  88. }
  89. #endif
  90. uint8_t RedFlyNBNS::service(void)
  91. {
  92. uint16_t len;
  93. uint8_t buf[NBNS_PACKETLEN+NBNSA_PACKETLEN];
  94. NBNS_Packet *nbns;
  95. char name[16+1];
  96. uint8_t type;
  97. if(!connected()) //listening port still open?
  98. {
  99. stop(); //stop and reset server
  100. beginUDP(); //start server
  101. return 1;
  102. }
  103. //data available?
  104. len = available();
  105. if(len >= (NBNS_PACKETLEN+NBNSQ_PACKETLEN))
  106. {
  107. //read data
  108. read(buf, sizeof(buf));
  109. flush(); //flush input buffer
  110. //check data for NBNS header and question
  111. nbns = (NBNS_Packet*) buf;
  112. if((nbns->qdcount == SWAP16(0x0001)) &&
  113. (nbns->data.qd.len == 32) &&
  114. (nbns->data.qd.type == SWAP16(NBNSQ_TYPE_NB)) &&
  115. (nbns->data.qd.clas == SWAP16(NBNSQ_CLASS_IN))) //NBNS question
  116. {
  117. type = decode(name, nbns->data.qd.name);
  118. if((type == 0x00) && (strcasecmp(name, devname) == 0))//0x00 = Workstation
  119. {
  120. //create NBNS answer
  121. nbns->id = nbns->id;
  122. nbns->flags_op = SWAP16(NBNS_FLAG_RESPONSE|NBNS_FLAG_AUTHORITY);
  123. nbns->qdcount = SWAP16(0x0000);
  124. nbns->ancount = SWAP16(0x0001);
  125. nbns->nscount = SWAP16(0x0000);
  126. nbns->arcount = SWAP16(0x0000);
  127. nbns->data.an.len = 32;
  128. nbns->data.an.type = SWAP16(NBNSA_TYPE_NB);
  129. nbns->data.an.clas = SWAP16(NBNSA_CLASS_IN);
  130. nbns->data.an.ttl = SWAP32(3600); //time to live 3600 sec = 1 hour
  131. nbns->data.an.rdlen = SWAP16(0x0006);
  132. nbns->data.an.flags = SWAP16(0x0000);
  133. RedFly.getlocalip(nbns->data.an.addr);
  134. encode(nbns->data.an.name, devname, 0x00); //0x00 = Workstation
  135. nbns->data.an.name[32] = 0;
  136. //send answer
  137. write(buf, NBNS_PACKETLEN+NBNSA_PACKETLEN);
  138. return 0xFF;
  139. }
  140. }
  141. }
  142. return 0;
  143. }
  144. //-------------------- Private --------------------
  145. uint8_t RedFlyNBNS::decode(char *dst, char *src)
  146. {
  147. uint8_t i, j;
  148. char c;
  149. for(i=0, j=0; i<15; i++)
  150. {
  151. c = (src[j++]-'A')<<4;
  152. c |= (src[j++]-'A')<<0;
  153. if(c == ' ')
  154. {
  155. break;
  156. }
  157. dst[i] = toupper(c);
  158. }
  159. dst[i] = 0;
  160. return (((src[30]-'A')<<4)|(src[31]-'A')); //0x00 = Workstation
  161. }
  162. void RedFlyNBNS::encode(char *dst, char *src, uint8_t type)
  163. {
  164. uint8_t i, j;
  165. char c;
  166. //encode name
  167. for(i=0, j=0; (i<15) && src[i]; i++)
  168. {
  169. c = toupper(src[i]);
  170. dst[j++] = 'A'+((c>>4)&0x0f);
  171. dst[j++] = 'A'+((c>>0)&0x0f);
  172. }
  173. //add spaces
  174. for(; i<15; i++)
  175. {
  176. dst[j++] = 'A'+((' '>>4)&0x0f);
  177. dst[j++] = 'A'+((' '>>0)&0x0f);
  178. }
  179. //set type (0x00 = Workstation)
  180. dst[j++] = 'A'+((type>>4)&0x0f);
  181. dst[j++] = 'A'+((type>>0)&0x0f);
  182. return;
  183. }