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