]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/libalias/alias_nbt.c
ssh: remove 11.x from FREEBSD-upgrade instructions
[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 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         u_char c;
255         int compress;
256
257         /* Following length field */
258
259         if (p == NULL || (char *)p >= pmax)
260                 return (NULL);
261
262         if (*p & 0xc0) {
263                 p = p + 2;
264                 if ((char *)p > pmax)
265                         return (NULL);
266                 return ((u_char *)p);
267         }
268         while ((*p & 0x3f) != 0x00) {
269                 s = p + 1;
270                 if (*p == 0x20)
271                         compress = 1;
272                 else
273                         compress = 0;
274
275                 /* Get next length field */
276                 p = (u_char *)(p + (*p & 0x3f) + 1);
277                 if ((char *)p > pmax) {
278                         p = NULL;
279                         break;
280                 }
281 #ifdef LIBALIAS_DEBUG
282                 printf(":");
283 #endif
284                 while (s < p) {
285                         if (compress == 1) {
286                                 c = (u_char) (((((*s & 0x0f) << 4) | (*(s + 1) & 0x0f)) - 0x11));
287 #ifdef LIBALIAS_DEBUG
288                                 if (isprint(c))
289                                         printf("%c", c);
290                                 else
291                                         printf("<0x%02x>", c);
292 #endif
293                                 s += 2;
294                         } else {
295 #ifdef LIBALIAS_DEBUG
296                                 printf("%c", *s);
297 #endif
298                                 s++;
299                         }
300                 }
301 #ifdef LIBALIAS_DEBUG
302                 printf(":");
303                 fflush(stdout);
304 #endif
305         }
306
307         /* Set up to out of Name field */
308         if (p == NULL || (char *)p >= pmax)
309                 p = NULL;
310         else
311                 p++;
312         return ((u_char *)p);
313 }
314
315 /*
316  * NetBios Datagram Handler (IP/UDP)
317  */
318 #define DGM_DIRECT_UNIQ         0x10
319 #define DGM_DIRECT_GROUP        0x11
320 #define DGM_BROADCAST           0x12
321 #define DGM_ERROR               0x13
322 #define DGM_QUERY               0x14
323 #define DGM_POSITIVE_RES        0x15
324 #define DGM_NEGATIVE_RES        0x16
325
326 static int
327 AliasHandleUdpNbt(
328     struct libalias   *la,
329     struct ip         *pip,     /* IP packet to examine/patch */
330     struct alias_link *lnk,
331     struct in_addr    *alias_address,
332     u_short            alias_port)
333 {
334         struct udphdr *uh;
335         NbtDataHeader *ndh;
336         u_char *p = NULL;
337         char *pmax;
338 #ifdef LIBALIAS_DEBUG
339         char addrbuf[INET_ADDRSTRLEN];
340 #endif
341
342         (void)la;
343         (void)lnk;
344
345         /* Calculate data length of UDP packet */
346         uh = (struct udphdr *)ip_next(pip);
347         pmax = (char *)uh + ntohs(uh->uh_ulen);
348
349         ndh = (NbtDataHeader *)udp_next(uh);
350         if ((char *)(ndh + 1) > pmax)
351                 return (-1);
352 #ifdef LIBALIAS_DEBUG
353         printf("\nType=%02x,", ndh->type);
354 #endif
355         switch (ndh->type) {
356         case DGM_DIRECT_UNIQ:
357         case DGM_DIRECT_GROUP:
358         case DGM_BROADCAST:
359                 p = (u_char *)ndh + 14;
360                 p = AliasHandleName(p, pmax);   /* Source Name */
361                 p = AliasHandleName(p, pmax);   /* Destination Name */
362                 break;
363         case DGM_ERROR:
364                 p = (u_char *)ndh + 11;
365                 break;
366         case DGM_QUERY:
367         case DGM_POSITIVE_RES:
368         case DGM_NEGATIVE_RES:
369                 p = (u_char *)ndh + 10;
370                 p = AliasHandleName(p, pmax);   /* Destination Name */
371                 break;
372         }
373         if (p == NULL || (char *)p > pmax)
374                 p = NULL;
375 #ifdef LIBALIAS_DEBUG
376         printf("%s:%d-->", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)),
377             ntohs(ndh->source_port));
378 #endif
379         /* Doing an IP address and Port number Translation */
380         if (uh->uh_sum != 0) {
381                 int acc;
382                 u_short *sptr;
383
384                 acc = ndh->source_port;
385                 acc -= alias_port;
386                 sptr = (u_short *)&(ndh->source_ip);
387                 acc += *sptr++;
388                 acc += *sptr;
389                 sptr = (u_short *)alias_address;
390                 acc -= *sptr++;
391                 acc -= *sptr;
392                 ADJUST_CHECKSUM(acc, uh->uh_sum);
393         }
394         ndh->source_ip = *alias_address;
395         ndh->source_port = alias_port;
396 #ifdef LIBALIAS_DEBUG
397         printf("%s:%d\n", inet_ntoa_r(ndh->source_ip, INET_NTOA_BUF(addrbuf)),
398             ntohs(ndh->source_port));
399         fflush(stdout);
400 #endif
401         return ((p == NULL) ? -1 : 0);
402 }
403
404 /* Question Section */
405 #define QS_TYPE_NB      0x0020
406 #define QS_TYPE_NBSTAT  0x0021
407 #define QS_CLAS_IN      0x0001
408 typedef struct {
409         u_short         type;   /* The type of Request */
410         u_short         class;  /* The class of Request */
411 } NBTNsQuestion;
412
413 static u_char *
414 AliasHandleQuestion(
415     u_short count,
416     NBTNsQuestion * q,
417     char *pmax,
418     NBTArguments * nbtarg)
419 {
420         (void)nbtarg;
421
422         while (count != 0) {
423                 /* Name Filed */
424                 q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax);
425
426                 if (q == NULL || (char *)(q + 1) > pmax) {
427                         q = NULL;
428                         break;
429                 }
430                 /* Type and Class filed */
431                 switch (ntohs(q->type)) {
432                 case QS_TYPE_NB:
433                 case QS_TYPE_NBSTAT:
434                         q = q + 1;
435                         break;
436                 default:
437 #ifdef LIBALIAS_DEBUG
438                         printf("\nUnknown Type on Question %0x\n", ntohs(q->type));
439 #endif
440                         break;
441                 }
442                 count--;
443         }
444
445         /* Set up to out of Question Section */
446         return ((u_char *)q);
447 }
448
449 /* Resource Record */
450 #define RR_TYPE_A       0x0001
451 #define RR_TYPE_NS      0x0002
452 #define RR_TYPE_NULL    0x000a
453 #define RR_TYPE_NB      0x0020
454 #define RR_TYPE_NBSTAT  0x0021
455 #define RR_CLAS_IN      0x0001
456 #define SizeOfNsResource        8
457 typedef struct {
458         u_short         type;
459         u_short         class;
460         unsigned int    ttl;
461         u_short         rdlen;
462 } NBTNsResource;
463
464 #define SizeOfNsRNB             6
465 typedef struct {
466         u_short         g:1, ont:2, resv:13;
467         struct in_addr  addr;
468 } NBTNsRNB;
469
470 static u_char *
471 AliasHandleResourceNB(
472     NBTNsResource *q,
473     char          *pmax,
474     NBTArguments  *nbtarg)
475 {
476         NBTNsRNB *nb;
477         u_short bcount;
478 #ifdef LIBALIAS_DEBUG
479         char oldbuf[INET_ADDRSTRLEN];
480         char newbuf[INET_ADDRSTRLEN];
481 #endif
482
483         if (q == NULL || (char *)(q + 1) > pmax)
484                 return (NULL);
485         /* Check out a length */
486         bcount = ntohs(q->rdlen);
487
488         /* Forward to Resource NB position */
489         nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource);
490
491         /* Processing all in_addr array */
492 #ifdef LIBALIAS_DEBUG
493         printf("NB rec[%s->%s, %dbytes] ",
494             inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)),
495             inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)),
496             bcount);
497 #endif
498         while (nb != NULL && bcount != 0) {
499                 if ((char *)(nb + 1) > pmax) {
500                         nb = NULL;
501                         break;
502                 }
503 #ifdef LIBALIAS_DEBUG
504                 printf("<%s>", inet_ntoa_r(nb->addr, INET_NTOA_BUF(newbuf)));
505 #endif
506                 if (!bcmp(&nbtarg->oldaddr, &nb->addr, sizeof(struct in_addr))) {
507                         if (*nbtarg->uh_sum != 0) {
508                                 int acc;
509                                 u_short *sptr;
510
511                                 sptr = (u_short *)&(nb->addr);
512                                 acc = *sptr++;
513                                 acc += *sptr;
514                                 sptr = (u_short *)&(nbtarg->newaddr);
515                                 acc -= *sptr++;
516                                 acc -= *sptr;
517                                 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
518                         }
519                         nb->addr = nbtarg->newaddr;
520 #ifdef LIBALIAS_DEBUG
521                         printf("O");
522 #endif
523                 }
524 #ifdef LIBALIAS_DEBUG
525                 else {
526                         printf(".");
527                 }
528 #endif
529                 nb = (NBTNsRNB *)((u_char *)nb + SizeOfNsRNB);
530                 bcount -= SizeOfNsRNB;
531         }
532         if (nb == NULL || (char *)(nb + 1) > pmax) {
533                 nb = NULL;
534         }
535         return ((u_char *)nb);
536 }
537
538 #define SizeOfResourceA         6
539 typedef struct {
540         struct in_addr  addr;
541 } NBTNsResourceA;
542
543 static u_char *
544 AliasHandleResourceA(
545     NBTNsResource *q,
546     char          *pmax,
547     NBTArguments  *nbtarg)
548 {
549         NBTNsResourceA *a;
550         u_short bcount;
551 #ifdef LIBALIAS_DEBUG
552         char oldbuf[INET_ADDRSTRLEN];
553         char newbuf[INET_ADDRSTRLEN];
554 #endif
555
556         if (q == NULL || (char *)(q + 1) > pmax)
557                 return (NULL);
558
559         /* Forward to Resource A position */
560         a = (NBTNsResourceA *)((u_char *)q + sizeof(NBTNsResource));
561
562         /* Check out of length */
563         bcount = ntohs(q->rdlen);
564
565         /* Processing all in_addr array */
566 #ifdef LIBALIAS_DEBUG
567         printf("Arec [%s->%s]",
568             inet_ntoa_r(nbtarg->oldaddr, INET_NTOA_BUF(oldbuf)),
569             inet_ntoa_r(nbtarg->newaddr, INET_NTOA_BUF(newbuf)));
570 #endif
571         while (bcount != 0) {
572                 if (a == NULL || (char *)(a + 1) > pmax)
573                         return (NULL);
574 #ifdef LIBALIAS_DEBUG
575                 printf("..%s", inet_ntoa_r(a->addr, INET_NTOA_BUF(newbuf)));
576 #endif
577                 if (!bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr))) {
578                         if (*nbtarg->uh_sum != 0) {
579                                 int acc;
580                                 u_short *sptr;
581
582                                 sptr = (u_short *)&(a->addr);   /* Old */
583                                 acc = *sptr++;
584                                 acc += *sptr;
585                                 sptr = (u_short *)&nbtarg->newaddr;     /* New */
586                                 acc -= *sptr++;
587                                 acc -= *sptr;
588                                 ADJUST_CHECKSUM(acc, *nbtarg->uh_sum);
589                         }
590                         a->addr = nbtarg->newaddr;
591                 }
592                 a++;            /* XXXX */
593                 bcount -= SizeOfResourceA;
594         }
595         if (a == NULL || (char *)(a + 1) > pmax)
596                 a = NULL;
597         return ((u_char *)a);
598 }
599
600 typedef struct {
601         u_short         opcode:4, flags:8, resv:4;
602 } NBTNsResourceNULL;
603
604 static u_char *
605 AliasHandleResourceNULL(
606     NBTNsResource *q,
607     char          *pmax,
608     NBTArguments  *nbtarg)
609 {
610         NBTNsResourceNULL *n;
611         u_short bcount;
612
613         (void)nbtarg;
614
615         if (q == NULL || (char *)(q + 1) > pmax)
616                 return (NULL);
617
618         /* Forward to Resource NULL position */
619         n = (NBTNsResourceNULL *)((u_char *)q + sizeof(NBTNsResource));
620
621         /* Check out of length */
622         bcount = ntohs(q->rdlen);
623
624         /* Processing all in_addr array */
625         while (bcount != 0) {
626                 if ((char *)(n + 1) > pmax) {
627                         n = NULL;
628                         break;
629                 }
630                 n++;
631                 bcount -= sizeof(NBTNsResourceNULL);
632         }
633         if ((char *)(n + 1) > pmax)
634                 n = NULL;
635
636         return ((u_char *)n);
637 }
638
639 static u_char *
640 AliasHandleResourceNS(
641     NBTNsResource *q,
642     char          *pmax,
643     NBTArguments  *nbtarg)
644 {
645         NBTNsResourceNULL *n;
646         u_short bcount;
647
648         (void)nbtarg;
649
650         if (q == NULL || (char *)(q + 1) > pmax)
651                 return (NULL);
652
653         /* Forward to Resource NULL position */
654         n = (NBTNsResourceNULL *)((u_char *)q + sizeof(NBTNsResource));
655
656         /* Check out of length */
657         bcount = ntohs(q->rdlen);
658
659         /* Resource Record Name Filed */
660         q = (NBTNsResource *)AliasHandleName((u_char *)n, pmax);        /* XXX */
661
662         if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
663                 return (NULL);
664         else
665                 return ((u_char *)n + bcount);
666 }
667
668 typedef struct {
669         u_short         numnames;
670 } NBTNsResourceNBSTAT;
671
672 static u_char *
673 AliasHandleResourceNBSTAT(
674     NBTNsResource *q,
675     char          *pmax,
676     NBTArguments  *nbtarg)
677 {
678         NBTNsResourceNBSTAT *n;
679         u_short bcount;
680
681         (void)nbtarg;
682
683         if (q == NULL || (char *)(q + 1) > pmax)
684                 return (NULL);
685
686         /* Forward to Resource NBSTAT position */
687         n = (NBTNsResourceNBSTAT *)((u_char *)q + sizeof(NBTNsResource));
688
689         /* Check out of length */
690         bcount = ntohs(q->rdlen);
691
692         if (q == NULL || (char *)((u_char *)n + bcount) > pmax)
693                 return (NULL);
694         else
695                 return ((u_char *)n + bcount);
696 }
697
698 static u_char *
699 AliasHandleResource(
700     u_short        count,
701     NBTNsResource *q,
702     char          *pmax,
703     NBTArguments  *nbtarg)
704 {
705         while (count != 0) {
706                 /* Resource Record Name Filed */
707                 q = (NBTNsResource *)AliasHandleName((u_char *)q, pmax);
708
709                 if (q == NULL || (char *)(q + 1) > pmax)
710                         break;
711 #ifdef LIBALIAS_DEBUG
712                 printf("type=%02x, count=%d\n", ntohs(q->type), count);
713 #endif
714
715                 /* Type and Class filed */
716                 switch (ntohs(q->type)) {
717                 case RR_TYPE_NB:
718                         q = (NBTNsResource *)AliasHandleResourceNB(
719                             q, pmax, nbtarg);
720                         break;
721                 case RR_TYPE_A:
722                         q = (NBTNsResource *)AliasHandleResourceA(
723                             q, pmax, nbtarg);
724                         break;
725                 case RR_TYPE_NS:
726                         q = (NBTNsResource *)AliasHandleResourceNS(
727                             q, pmax, nbtarg);
728                         break;
729                 case RR_TYPE_NULL:
730                         q = (NBTNsResource *)AliasHandleResourceNULL(
731                             q, pmax, nbtarg);
732                         break;
733                 case RR_TYPE_NBSTAT:
734                         q = (NBTNsResource *)AliasHandleResourceNBSTAT(
735                             q, pmax, nbtarg);
736                         break;
737                 default:
738 #ifdef LIBALIAS_DEBUG
739                         printf(
740                             "\nUnknown Type of Resource %0x\n",
741                             ntohs(q->type)
742                             );
743                         fflush(stdout);
744 #endif
745                         break;
746                 }
747                 count--;
748         }
749         return ((u_char *)q);
750 }
751
752 static int
753 AliasHandleUdpNbtNS(
754     struct libalias   *la,
755     struct ip         *pip,     /* IP packet to examine/patch */
756     struct alias_link *lnk,
757     struct in_addr    *alias_address,
758     u_short           *alias_port,
759     struct in_addr    *original_address,
760     u_short           *original_port)
761 {
762         struct udphdr *uh;
763         NbtNSHeader *nsh;
764         u_char *p;
765         char *pmax;
766         NBTArguments nbtarg;
767
768         (void)la;
769         (void)lnk;
770
771         /* Set up Common Parameter */
772         nbtarg.oldaddr = *alias_address;
773         nbtarg.oldport = *alias_port;
774         nbtarg.newaddr = *original_address;
775         nbtarg.newport = *original_port;
776
777         /* Calculate data length of UDP packet */
778         uh = (struct udphdr *)ip_next(pip);
779         nbtarg.uh_sum = &(uh->uh_sum);
780         nsh = (NbtNSHeader *)udp_next(uh);
781         p = (u_char *)(nsh + 1);
782         pmax = (char *)uh + ntohs(uh->uh_ulen);
783
784         if ((char *)(nsh + 1) > pmax)
785                 return (-1);
786
787 #ifdef LIBALIAS_DEBUG
788         printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x"
789             ", an=%04x, ns=%04x, ar=%04x, [%d]-->",
790             nsh->dir ? "Response" : "Request",
791             nsh->nametrid,
792             nsh->opcode,
793             nsh->nmflags,
794             nsh->rcode,
795             ntohs(nsh->qdcount),
796             ntohs(nsh->ancount),
797             ntohs(nsh->nscount),
798             ntohs(nsh->arcount),
799             (u_char *)p - (u_char *)nsh
800             );
801 #endif
802
803         /* Question Entries */
804         if (ntohs(nsh->qdcount) != 0) {
805                 p = AliasHandleQuestion(
806                     ntohs(nsh->qdcount),
807                     (NBTNsQuestion *)p,
808                     pmax,
809                     &nbtarg
810                     );
811         }
812         /* Answer Resource Records */
813         if (ntohs(nsh->ancount) != 0) {
814                 p = AliasHandleResource(
815                     ntohs(nsh->ancount),
816                     (NBTNsResource *)p,
817                     pmax,
818                     &nbtarg
819                     );
820         }
821         /* Authority Resource Recodrs */
822         if (ntohs(nsh->nscount) != 0) {
823                 p = AliasHandleResource(
824                     ntohs(nsh->nscount),
825                     (NBTNsResource *)p,
826                     pmax,
827                     &nbtarg
828                     );
829         }
830         /* Additional Resource Recodrs */
831         if (ntohs(nsh->arcount) != 0) {
832                 p = AliasHandleResource(
833                     ntohs(nsh->arcount),
834                     (NBTNsResource *)p,
835                     pmax,
836                     &nbtarg
837                     );
838         }
839 #ifdef LIBALIAS_DEBUG
840         PrintRcode(nsh->rcode);
841 #endif
842         return ((p == NULL) ? -1 : 0);
843 }