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