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