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