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