VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/libalias/alias_nbt.c@ 103068

Last change on this file since 103068 was 83597, checked in by vboxsync, 5 years ago

NAT: bugref:9694 - libalias NBT - IP header is verified, but UDP
header is not, so cross check UDP length against IP header.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette