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