xref: /dragonfly/lib/libalias/alias_nbt.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1 /*-
2  * Written by Atsushi Murai <amurai@spec.co.jp>
3  * Copyright (c) 1998, System Planning and Engineering Co.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/lib/libalias/alias_nbt.c,v 1.4.2.3 2001/08/01 09:52:26 obrien Exp $
28  * $DragonFly: src/lib/libalias/alias_nbt.c,v 1.4 2006/03/18 19:43:18 swildner Exp $
29  *
30  *  TODO:
31  *       oClean up.
32  *       oConsidering for word alignment for other platform.
33  */
34 /*
35     alias_nbt.c performs special processing for NetBios over TCP/IP
36     sessions by UDP.
37 
38     Initial version:  May, 1998  (Atsushi Murai <amurai@spec.co.jp>)
39 
40     See HISTORY file for record of revisions.
41 */
42 
43 /* Includes */
44 #include <sys/param.h>
45 #include <ctype.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 #include <netinet/ip.h>
52 #include <netinet/udp.h>
53 #include <netinet/tcp.h>
54 
55 #include "alias_local.h"
56 
57 typedef struct {
58           struct in_addr                oldaddr;
59           u_short                       oldport;
60           struct in_addr                newaddr;
61           u_short                       newport;
62           u_short                       *uh_sum;
63 } NBTArguments;
64 
65 typedef struct {
66           unsigned char   type;
67           unsigned char   flags;
68           u_short             id;
69           struct in_addr  source_ip;
70           u_short                       source_port;
71           u_short                       len;
72           u_short                       offset;
73 } NbtDataHeader;
74 
75 #define OpQuery               0
76 #define OpUnknown   4
77 #define OpRegist    5
78 #define OpRelease   6
79 #define OpWACK                7
80 #define OpRefresh   8
81 typedef struct {
82           u_short                       nametrid;
83           u_short             dir:1, opcode:4, nmflags:7, rcode:4;
84           u_short                       qdcount;
85           u_short                       ancount;
86           u_short                       nscount;
87           u_short                       arcount;
88 } NbtNSHeader;
89 
90 #define FMT_ERR               0x1
91 #define SRV_ERR               0x2
92 #define IMP_ERR               0x4
93 #define RFS_ERR               0x5
94 #define ACT_ERR               0x6
95 #define CFT_ERR               0x7
96 
97 
98 #ifdef DEBUG
PrintRcode(u_char rcode)99 static void PrintRcode( u_char rcode )  {
100 
101           switch (rcode) {
102                     case FMT_ERR:
103                               printf("\nFormat Error.");
104                     case SRV_ERR:
105                               printf("\nSever failure.");
106                     case IMP_ERR:
107                               printf("\nUnsupported request error.\n");
108                     case RFS_ERR:
109                               printf("\nRefused error.\n");
110                     case ACT_ERR:
111                               printf("\nActive error.\n");
112                     case CFT_ERR:
113                               printf("\nName in conflict error.\n");
114                     default:
115                               printf("\n??\?=%0x\n", rcode );
116 
117           }
118 }
119 #endif
120 
121 
122 /* Handling Name field */
AliasHandleName(u_char * p,char * pmax)123 static u_char *AliasHandleName ( u_char *p, char *pmax ) {
124 
125           u_char *s;
126 #ifdef DEBUG
127           u_char c;
128 #endif
129           int                 compress;
130 
131           /* Following length field */
132 
133           if (p == NULL || (char *)p >= pmax)
134                     return(NULL);
135 
136           if (*p & 0xc0 ) {
137                     p = p + 2;
138                     if ((char *)p > pmax)
139                               return(NULL);
140                     return ((u_char *)p);
141           }
142           while ( ( *p & 0x3f) != 0x00 ) {
143                     s = p + 1;
144                     if ( *p == 0x20 )
145                               compress = 1;
146                     else
147                               compress = 0;
148 
149                     /* Get next length field */
150                     p = (u_char *)(p + (*p & 0x3f) + 1);
151                     if ((char *)p > pmax) {
152                               p = NULL;
153                               break;
154                     }
155 #ifdef DEBUG
156                     printf(":");
157 #endif
158                     while (s < p) {
159                               if ( compress == 1 ) {
160 #ifdef DEBUG
161                                         c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11));
162                                         if (isprint( c ) )
163                                                   printf("%c", c );
164                                         else
165                                                   printf("<0x%02x>", c );
166 #endif
167                                         s +=2;
168                               } else {
169 #ifdef DEBUG
170                                         printf("%c", *s);
171 #endif
172                                         s++;
173                               }
174                     }
175 #ifdef DEBUG
176                     printf(":");
177 #endif
178                     fflush(stdout);
179     }
180 
181           /* Set up to out of Name field */
182           if (p == NULL || (char *)p >= pmax)
183               p = NULL;
184           else
185               p++;
186           return ((u_char *)p);
187 }
188 
189 /*
190  * NetBios Datagram Handler (IP/UDP)
191  */
192 #define DGM_DIRECT_UNIQ                 0x10
193 #define DGM_DIRECT_GROUP      0x11
194 #define DGM_BROADCAST                   0x12
195 #define DGM_ERROR                       0x13
196 #define DGM_QUERY                       0x14
197 #define DGM_POSITIVE_RES      0x15
198 #define DGM_NEGATIVE_RES      0x16
199 
AliasHandleUdpNbt(struct ip * pip,struct alias_link * link,struct in_addr * alias_address,u_short alias_port)200 int AliasHandleUdpNbt(
201           struct ip                               *pip,      /* IP packet to examine/patch */
202           struct alias_link   *link,
203           struct in_addr                *alias_address,
204     u_short                   alias_port
205 ) {
206     struct udphdr * uh;
207     NbtDataHeader   *ndh;
208     u_char                    *p = NULL;
209     char            *pmax;
210 
211     /* Calculate data length of UDP packet */
212     uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
213     pmax = (char *)uh + ntohs( uh->uh_ulen );
214 
215           ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr)));
216     if ((char *)(ndh + 1) > pmax)
217               return(-1);
218 #ifdef DEBUG
219           printf("\nType=%02x,", ndh->type );
220 #endif
221           switch ( ndh->type ) {
222                     case DGM_DIRECT_UNIQ:
223                     case DGM_DIRECT_GROUP:
224                     case DGM_BROADCAST:
225                               p = (u_char *)ndh + 14;
226                         p = AliasHandleName ( p, pmax ); /* Source Name */
227                         p = AliasHandleName ( p, pmax ); /* Destination Name */
228                               break;
229                     case DGM_ERROR:
230                               p = (u_char *)ndh + 11;
231                               break;
232                     case DGM_QUERY:
233                     case DGM_POSITIVE_RES:
234                     case DGM_NEGATIVE_RES:
235                               p = (u_char *)ndh + 10;
236                         p = AliasHandleName ( p, pmax ); /* Destination Name */
237                               break;
238           }
239     if (p == NULL || (char *)p > pmax)
240               p = NULL;
241 #ifdef DEBUG
242           printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
243 #endif
244           /* Doing a IP address and Port number Translation */
245           if ( uh->uh_sum != 0 ) {
246                     int                                     acc;
247                     u_short                       *sptr;
248                     acc  = ndh->source_port;
249                     acc -= alias_port;
250                     sptr = (u_short *) &(ndh->source_ip);
251                     acc += *sptr++;
252                     acc += *sptr;
253                     sptr = (u_short *) alias_address;
254                     acc -= *sptr++;
255                     acc -= *sptr;
256                     ADJUST_CHECKSUM(acc, uh->uh_sum);
257           }
258     ndh->source_ip = *alias_address;
259     ndh->source_port = alias_port;
260 #ifdef DEBUG
261           printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) );
262           fflush(stdout);
263 #endif
264     return((p == NULL) ? -1 : 0);
265 }
266 /* Question Section */
267 #define QS_TYPE_NB            0x0020
268 #define QS_TYPE_NBSTAT        0x0021
269 #define QS_CLAS_IN            0x0001
270 typedef struct {
271           u_short   type;     /* The type of Request */
272           u_short   class;    /* The class of Request */
273 } NBTNsQuestion;
274 
275 static u_char *
AliasHandleQuestion(u_short count,NBTNsQuestion * q,char * pmax,NBTArguments * nbtarg)276 AliasHandleQuestion(
277     u_short count,
278                                                                       NBTNsQuestion *q,
279     char *pmax,
280                                                                       NBTArguments  *nbtarg)
281 {
282 
283           while ( count != 0 ) {
284                     /* Name Filed */
285                     q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
286 
287                     if (q == NULL || (char *)(q + 1) > pmax) {
288                               q = NULL;
289                               break;
290                     }
291 
292                     /* Type and Class filed */
293                     switch ( ntohs(q->type) ) {
294                               case QS_TYPE_NB:
295                               case QS_TYPE_NBSTAT:
296                                         q= q+1;
297                               break;
298                               default:
299 #ifdef DEBUG
300                                         printf("\nUnknown Type on Question %0x\n", ntohs(q->type) );
301 #endif
302                               break;
303                     }
304                     count--;
305           }
306 
307           /* Set up to out of Question Section */
308           return ((u_char *)q);
309 }
310 
311 /* Resource Record */
312 #define RR_TYPE_A             0x0001
313 #define RR_TYPE_NS            0x0002
314 #define RR_TYPE_NULL          0x000a
315 #define RR_TYPE_NB            0x0020
316 #define RR_TYPE_NBSTAT        0x0021
317 #define RR_CLAS_IN            0x0001
318 #define SizeOfNsResource      8
319 typedef struct {
320           u_short type;
321           u_short class;
322           unsigned int ttl;
323           u_short rdlen;
324 } NBTNsResource;
325 
326 #define SizeOfNsRNB                     6
327 typedef struct {
328           u_short g:1, ont:2, resv:13;
329           struct    in_addr   addr;
330 } NBTNsRNB;
331 
332 static u_char *
AliasHandleResourceNB(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)333 AliasHandleResourceNB(
334     NBTNsResource *q,
335     char *pmax,
336                                                                          NBTArguments  *nbtarg)
337 {
338           NBTNsRNB  *nb;
339           u_short bcount;
340 
341           if (q == NULL || (char *)(q + 1) > pmax)
342                     return(NULL);
343           /* Check out a length */
344           bcount = ntohs(q->rdlen);
345 
346           /* Forward to Resource NB position */
347           nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
348 
349           /* Processing all in_addr array */
350 #ifdef DEBUG
351           printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr));
352             printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount);
353 #endif
354           while ( nb != NULL && bcount != 0 )  {
355                     if ((char *)(nb + 1) > pmax) {
356                               nb = NULL;
357                               break;
358                     }
359 #ifdef DEBUG
360                     printf("<%s>", inet_ntoa(nb->addr) );
361 #endif
362                     if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) {
363                               if ( *nbtarg->uh_sum != 0 ) {
364                     int acc;
365                     u_short *sptr;
366 
367                     sptr = (u_short *) &(nb->addr);
368                     acc = *sptr++;
369                     acc += *sptr;
370                     sptr = (u_short *) &(nbtarg->newaddr);
371                     acc -= *sptr++;
372                     acc -= *sptr;
373                     ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
374                               }
375 
376                               nb->addr = nbtarg->newaddr;
377 #ifdef DEBUG
378                               printf("O");
379 #endif
380                     }
381 #ifdef DEBUG
382                      else {
383                               printf(".");
384                     }
385 #endif
386                     nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
387                     bcount -= SizeOfNsRNB;
388           }
389           if (nb == NULL || (char *)(nb + 1) > pmax) {
390                     nb = NULL;
391           }
392 
393           return ((u_char *)nb);
394 }
395 
396 #define SizeOfResourceA                 6
397 typedef struct {
398           struct    in_addr   addr;
399 } NBTNsResourceA;
400 
401 static u_char *
AliasHandleResourceA(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)402 AliasHandleResourceA(
403     NBTNsResource *q,
404     char *pmax,
405                                                                         NBTArguments  *nbtarg)
406 {
407           NBTNsResourceA      *a;
408           u_short bcount;
409 
410           if (q == NULL || (char *)(q + 1) > pmax)
411                     return(NULL);
412 
413           /* Forward to Resource A position */
414           a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) );
415 
416           /* Check out of length */
417           bcount = ntohs(q->rdlen);
418 
419           /* Processing all in_addr array */
420 #ifdef DEBUG
421           printf("Arec [%s", inet_ntoa(nbtarg->oldaddr));
422         printf("->%s]",inet_ntoa(nbtarg->newaddr ));
423 #endif
424           while ( bcount != 0 )  {
425                     if (a == NULL || (char *)(a + 1) > pmax)
426                               return(NULL);
427 #ifdef DEBUG
428                     printf("..%s", inet_ntoa(a->addr) );
429 #endif
430                     if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) {
431                               if ( *nbtarg->uh_sum != 0 ) {
432                     int acc;
433                     u_short *sptr;
434 
435                     sptr = (u_short *) &(a->addr);                     /* Old */
436                     acc = *sptr++;
437                     acc += *sptr;
438                     sptr = (u_short *) &nbtarg->newaddr; /* New */
439                     acc -= *sptr++;
440                     acc -= *sptr;
441                     ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
442                               }
443 
444                               a->addr = nbtarg->newaddr;
445                     }
446                     a++;      /*XXXX*/
447                     bcount -= SizeOfResourceA;
448           }
449           if (a == NULL || (char *)(a + 1) > pmax)
450                     a =  NULL;
451           return ((u_char *)a);
452 }
453 
454 typedef struct {
455           u_short opcode:4, flags:8, resv:4;
456 } NBTNsResourceNULL;
457 
458 static u_char *
AliasHandleResourceNULL(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)459 AliasHandleResourceNULL(
460     NBTNsResource *q,
461     char *pmax,
462                                                                            NBTArguments  *nbtarg)
463 {
464           NBTNsResourceNULL   *n;
465           u_short bcount;
466 
467           if (q == NULL || (char *)(q + 1) > pmax)
468                     return(NULL);
469 
470           /* Forward to Resource NULL position */
471           n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
472 
473           /* Check out of length */
474           bcount = ntohs(q->rdlen);
475 
476           /* Processing all in_addr array */
477           while ( bcount != 0 )  {
478                     if ((char *)(n + 1) > pmax) {
479                               n = NULL;
480                               break;
481                     }
482                     n++;
483                     bcount -= sizeof(NBTNsResourceNULL);
484           }
485           if ((char *)(n + 1) > pmax)
486                     n = NULL;
487 
488           return ((u_char *)n);
489 }
490 
491 static u_char *
AliasHandleResourceNS(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)492 AliasHandleResourceNS(
493     NBTNsResource *q,
494     char *pmax,
495                                                                            NBTArguments  *nbtarg)
496 {
497           NBTNsResourceNULL   *n;
498           u_short bcount;
499 
500           if (q == NULL || (char *)(q + 1) > pmax)
501                     return(NULL);
502 
503           /* Forward to Resource NULL position */
504           n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) );
505 
506           /* Check out of length */
507           bcount = ntohs(q->rdlen);
508 
509           /* Resource Record Name Filed */
510           q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */
511 
512           if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
513                     return(NULL);
514           else
515           return ((u_char *)n + bcount);
516 }
517 
518 typedef struct {
519           u_short   numnames;
520 } NBTNsResourceNBSTAT;
521 
522 static u_char *
AliasHandleResourceNBSTAT(NBTNsResource * q,char * pmax,NBTArguments * nbtarg)523 AliasHandleResourceNBSTAT(
524     NBTNsResource *q,
525     char *pmax,
526                                                                              NBTArguments  *nbtarg)
527 {
528           NBTNsResourceNBSTAT *n;
529           u_short bcount;
530 
531           if (q == NULL || (char *)(q + 1) > pmax)
532                     return(NULL);
533 
534           /* Forward to Resource NBSTAT position */
535           n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) );
536 
537           /* Check out of length */
538           bcount = ntohs(q->rdlen);
539 
540           if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
541                     return(NULL);
542           else
543           return ((u_char *)n + bcount);
544 }
545 
546 static u_char *
AliasHandleResource(u_short count,NBTNsResource * q,char * pmax,NBTArguments * nbtarg)547 AliasHandleResource(
548     u_short count,
549                                                                       NBTNsResource *q,
550     char *pmax,
551     NBTArguments
552     *nbtarg)
553 {
554           while ( count != 0 ) {
555                     /* Resource Record Name Filed */
556                     q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax );
557 
558                     if (q == NULL || (char *)(q + 1) > pmax)
559                               break;
560 #ifdef DEBUG
561                     printf("type=%02x, count=%d\n", ntohs(q->type), count );
562 #endif
563 
564                     /* Type and Class filed */
565                     switch ( ntohs(q->type) ) {
566                               case RR_TYPE_NB:
567                                         q = (NBTNsResource *)AliasHandleResourceNB(
568                                             q,
569                                             pmax,
570                                             nbtarg
571                                         );
572                                         break;
573                               case RR_TYPE_A:
574                                         q = (NBTNsResource *)AliasHandleResourceA(
575                                             q,
576                                             pmax,
577                                             nbtarg
578                                         );
579                                         break;
580                               case RR_TYPE_NS:
581                                         q = (NBTNsResource *)AliasHandleResourceNS(
582                                             q,
583                                             pmax,
584                                             nbtarg
585                                         );
586                                         break;
587                               case RR_TYPE_NULL:
588                                         q = (NBTNsResource *)AliasHandleResourceNULL(
589                                             q,
590                                             pmax,
591                                             nbtarg
592                                         );
593                                         break;
594                               case RR_TYPE_NBSTAT:
595                                         q = (NBTNsResource *)AliasHandleResourceNBSTAT(
596                                             q,
597                                             pmax,
598                                             nbtarg
599                                         );
600                                         break;
601                               default:
602 #ifdef DEBUG
603                                         printf(
604                                             "\nUnknown Type of Resource %0x\n",
605                                             ntohs(q->type)
606                                         );
607 #endif
608                                         break;
609                     }
610                     count--;
611           }
612           fflush(stdout);
613           return ((u_char *)q);
614 }
615 
AliasHandleUdpNbtNS(struct ip * pip,struct alias_link * link,struct in_addr * alias_address,u_short * alias_port,struct in_addr * original_address,u_short * original_port)616 int AliasHandleUdpNbtNS(
617           struct ip                               *pip,      /* IP packet to examine/patch */
618           struct alias_link   *link,
619           struct in_addr                *alias_address,
620           u_short                       *alias_port,
621           struct in_addr                *original_address,
622           u_short                       *original_port )
623 {
624     struct udphdr * uh;
625           NbtNSHeader           * nsh;
626           u_char                * p;
627           char                *pmax;
628           NBTArguments    nbtarg;
629 
630           /* Set up Common Parameter */
631           nbtarg.oldaddr      =         *alias_address;
632           nbtarg.oldport      =         *alias_port;
633           nbtarg.newaddr      =         *original_address;
634           nbtarg.newport      =         *original_port;
635 
636     /* Calculate data length of UDP packet */
637     uh =  (struct udphdr *) ((char *) pip + (pip->ip_hl << 2));
638           nbtarg.uh_sum       =         &(uh->uh_sum);
639           nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr)));
640           p = (u_char *)(nsh + 1);
641     pmax = (char *)uh + ntohs( uh->uh_ulen );
642 
643     if ((char *)(nsh + 1) > pmax)
644           return(-1);
645 
646 #ifdef DEBUG
647     printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
648              ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
649                     nsh->dir ? "Response": "Request",
650                     nsh->nametrid,
651                     nsh->opcode,
652                     nsh->nmflags,
653                     nsh->rcode,
654                     ntohs(nsh->qdcount),
655                     ntohs(nsh->ancount),
656                     ntohs(nsh->nscount),
657                     ntohs(nsh->arcount),
658           (u_char *)p -(u_char *)nsh
659     );
660 #endif
661 
662           /* Question Entries */
663           if (ntohs(nsh->qdcount) !=0 ) {
664           p = AliasHandleQuestion(
665               ntohs(nsh->qdcount),
666               (NBTNsQuestion *)p,
667               pmax,
668               &nbtarg
669           );
670           }
671 
672           /* Answer Resource Records */
673           if (ntohs(nsh->ancount) !=0 ) {
674           p = AliasHandleResource(
675               ntohs(nsh->ancount),
676               (NBTNsResource *)p,
677               pmax,
678               &nbtarg
679           );
680           }
681 
682           /* Authority Resource Recodrs */
683           if (ntohs(nsh->nscount) !=0 ) {
684           p = AliasHandleResource(
685               ntohs(nsh->nscount),
686               (NBTNsResource *)p,
687               pmax,
688               &nbtarg
689           );
690           }
691 
692           /* Additional Resource Recodrs */
693           if (ntohs(nsh->arcount) !=0 ) {
694           p = AliasHandleResource(
695               ntohs(nsh->arcount),
696               (NBTNsResource *)p,
697               pmax,
698               &nbtarg
699           );
700           }
701 
702 #ifdef DEBUG
703                     PrintRcode(nsh->rcode);
704 #endif
705     return ((p == NULL) ? -1 : 0);
706 }
707