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

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Domain header conversion routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "domain.h"
  7. static int dn_expand(uint8 *msg,uint8 *eom,uint8 *compressed,char *full,
  8. int fullen);
  9. static uint8 *getq(struct rr **rrpp,uint8 *msg,uint8 *cp);
  10. static uint8 *ntohrr(struct rr **rrpp,uint8 *msg,uint8 *cp);
  11. int
  12. ntohdomain(dhdr,bpp)
  13. register struct dhdr *dhdr;
  14. struct mbuf **bpp;
  15. {
  16. uint16 tmp,len;
  17. register uint16 i;
  18. uint8 *msg,*cp;
  19. struct rr **rrpp;
  20. len = len_p(*bpp);
  21. msg = mallocw(len);
  22. pullup(bpp,msg,len);
  23. memset(dhdr,0,sizeof(*dhdr));
  24. dhdr->id = get16(&msg[0]);
  25. tmp = get16(&msg[2]);
  26. if(tmp & 0x8000)
  27. dhdr->qr = 1;
  28. dhdr->opcode = (tmp >> 11) & 0xf;
  29. if(tmp & 0x0400)
  30. dhdr->aa = 1;
  31. if(tmp & 0x0200)
  32. dhdr->tc = 1;
  33. if(tmp & 0x0100)
  34. dhdr->rd = 1;
  35. if(tmp & 0x0080)
  36. dhdr->ra = 1;
  37. dhdr->rcode = tmp & 0xf;
  38. dhdr->qdcount = get16(&msg[4]);
  39. dhdr->ancount = get16(&msg[6]);
  40. dhdr->nscount = get16(&msg[8]);
  41. dhdr->arcount = get16(&msg[10]);
  42. /* Now parse the variable length sections */
  43. cp = &msg[12];
  44. /* Question section */
  45. rrpp = &dhdr->questions;
  46. for(i=0;i<dhdr->qdcount;i++){
  47. if((cp = getq(rrpp,msg,cp)) == NULL){
  48. free(msg);
  49. return -1;
  50. }
  51. (*rrpp)->source = RR_QUESTION;
  52. rrpp = &(*rrpp)->next;
  53. }
  54. *rrpp = NULL;
  55. /* Answer section */
  56. rrpp = &dhdr->answers;
  57. for(i=0;i<dhdr->ancount;i++){
  58. if((cp = ntohrr(rrpp,msg,cp)) == NULL){
  59. free(msg);
  60. return -1;
  61. }
  62. (*rrpp)->source = RR_ANSWER;
  63. rrpp = &(*rrpp)->next;
  64. }
  65. *rrpp = NULL;
  66. /* Name server (authority) section */
  67. rrpp = &dhdr->authority;
  68. for(i=0;i<dhdr->nscount;i++){
  69. if((cp = ntohrr(rrpp,msg,cp)) == NULL){
  70. free(msg);
  71. return -1;
  72. }
  73. (*rrpp)->source = RR_AUTHORITY;
  74. rrpp = &(*rrpp)->next;
  75. }
  76. *rrpp = NULL;
  77. /* Additional section */
  78. rrpp = &dhdr->additional;
  79. for(i=0;i<dhdr->arcount;i++){
  80. if((cp = ntohrr(rrpp,msg,cp)) == NULL){
  81. free(msg);
  82. return -1;
  83. }
  84. (*rrpp)->source = RR_ADDITIONAL;
  85. rrpp = &(*rrpp)->next;
  86. }
  87. *rrpp = NULL;
  88. free(msg);
  89. return 0;
  90. }
  91. static uint8 *
  92. getq(rrpp,msg,cp)
  93. struct rr **rrpp;
  94. uint8 *msg;
  95. uint8 *cp;
  96. {
  97. register struct rr *rrp;
  98. int len;
  99. char *name;
  100. *rrpp = rrp = (struct rr *)callocw(1,sizeof(struct rr));
  101. name = mallocw(512);
  102. len = dn_expand(msg,NULL,cp,name,512);
  103. if(len == -1){
  104. free(name);
  105. return NULL;
  106. }
  107. cp += len;
  108. rrp->name = strdup(name);
  109. rrp->type = get16(cp);
  110. cp += 2;
  111. rrp->class = get16(cp);
  112. cp += 2;
  113. rrp->ttl = 0;
  114. rrp->rdlength = 0;
  115. free(name);
  116. return cp;
  117. }
  118. /* Read a resource record from a domain message into a host structure */
  119. static uint8 *
  120. ntohrr(rrpp,msg,cp)
  121. struct rr **rrpp; /* Where to allocate resource record structure */
  122. uint8 *msg; /* Pointer to beginning of domain message */
  123. uint8 *cp; /* Pointer to start of encoded RR record */
  124. {
  125. register struct rr *rrp;
  126. int len;
  127. char *name;
  128. *rrpp = rrp = (struct rr *)callocw(1,sizeof(struct rr));
  129. name = mallocw(512);
  130. if((len = dn_expand(msg,NULL,cp,name,512)) == -1){
  131. free(name);
  132. return NULL;
  133. }
  134. cp += len;
  135. rrp->name = strdup(name);
  136. rrp->type = get16(cp);
  137. cp += 2;
  138. rrp->class = get16(cp);
  139. cp+= 2;
  140. rrp->ttl = get32(cp);
  141. cp += 4;
  142. rrp->rdlength = get16(cp);
  143. cp += 2;
  144. switch(rrp->type){
  145. case TYPE_A:
  146. /* Just read the address directly into the structure */
  147. rrp->rdata.addr = get32(cp);
  148. cp += 4;
  149. break;
  150. case TYPE_CNAME:
  151. case TYPE_MB:
  152. case TYPE_MG:
  153. case TYPE_MR:
  154. case TYPE_NS:
  155. case TYPE_PTR:
  156. /* These types all consist of a single domain name;
  157.  * convert it to ascii format
  158.  */
  159. len = dn_expand(msg,NULL,cp,name,512);
  160. if(len == -1){
  161. free(name);
  162. return NULL;
  163. }
  164. rrp->rdata.name = strdup(name);
  165. rrp->rdlength = strlen(name);
  166. cp += len;
  167. break;
  168. case TYPE_HINFO:
  169. len = *cp++;
  170. rrp->rdata.hinfo.cpu = mallocw(len+1);
  171. strncpy(rrp->rdata.hinfo.cpu,(char *)cp,len);
  172. cp += len;
  173. len = *cp++;
  174. rrp->rdata.hinfo.os = mallocw(len+1);
  175. strncpy(rrp->rdata.hinfo.os,(char *)cp,len);
  176. cp += len;
  177. break;
  178. case TYPE_MX:
  179. rrp->rdata.mx.pref = get16(cp);
  180. cp += 2;
  181. /* Get domain name of exchanger */
  182. len = dn_expand(msg,NULL,cp,name,512);
  183. if(len == -1){
  184. free(name);
  185. return NULL;
  186. }
  187. rrp->rdata.mx.exch = strdup(name);
  188. cp += len;
  189. break;
  190. case TYPE_SOA:
  191. /* Get domain name of name server */
  192. len = dn_expand(msg,NULL,cp,name,512);
  193. if(len == -1){
  194. free(name);
  195. return NULL;
  196. }
  197. rrp->rdata.soa.mname = strdup(name);
  198. cp += len;
  199. /* Get domain name of responsible person */
  200. len = dn_expand(msg,NULL,cp,name,512);
  201. if(len == -1){
  202. free(name);
  203. return NULL;
  204. }
  205. rrp->rdata.soa.rname = strdup(name);
  206. cp += len;
  207. rrp->rdata.soa.serial = get32(cp);
  208. cp += 4;
  209. rrp->rdata.soa.refresh = get32(cp);
  210. cp += 4;
  211. rrp->rdata.soa.retry = get32(cp);
  212. cp += 4;
  213. rrp->rdata.soa.expire = get32(cp);
  214. cp += 4;
  215. rrp->rdata.soa.minimum = get32(cp);
  216. cp += 4;
  217. break;
  218. case TYPE_TXT:
  219. /* Just stash */
  220. rrp->rdata.data = mallocw(rrp->rdlength);
  221. memcpy(rrp->rdata.data,cp,rrp->rdlength);
  222. cp += rrp->rdlength;
  223. break;
  224. default:
  225. /* Ignore */
  226. cp += rrp->rdlength;
  227. break;
  228. }
  229. free(name);
  230. return cp;
  231. }
  232. /* Convert a compressed domain name to the human-readable form */
  233. static int
  234. dn_expand(msg,eom,compressed,full,fullen)
  235. uint8 *msg; /* Complete domain message */
  236. uint8 *eom;
  237. uint8 *compressed; /* Pointer to compressed name */
  238. char *full; /* Pointer to result buffer */
  239. int fullen; /* Length of same */
  240. {
  241. unsigned int slen; /* Length of current segment */
  242. register uint8 *cp;
  243. int clen = 0; /* Total length of compressed name */
  244. int indirect = 0; /* Set if indirection encountered */
  245. int nseg = 0; /* Total number of segments in name */
  246. cp = compressed;
  247. for(;;){
  248. slen = *cp++; /* Length of this segment */
  249. if(!indirect)
  250. clen++;
  251. if((slen & 0xc0) == 0xc0){
  252. if(!indirect)
  253. clen++;
  254. indirect = 1;
  255. /* Follow indirection */
  256. cp = &msg[((slen & 0x3f)<<8) + *cp];
  257. slen = *cp++;
  258. }
  259. if(slen == 0) /* zero length == all done */
  260. break;
  261. fullen -= slen + 1;
  262. if(fullen < 0)
  263. return -1;
  264. if(!indirect)
  265. clen += slen;
  266. while(slen-- != 0)
  267. *full++ = (char)*cp++;
  268. *full++ = '.';
  269. nseg++;
  270. }
  271. if(nseg == 0){
  272. /* Root name; represent as single dot */
  273. *full++ = '.';
  274. fullen--;
  275. }
  276. *full++ = '';
  277. fullen--;
  278. return clen; /* Length of compressed message */
  279. }