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