KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > netbios > NetBIOSPacket


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.netbios;
18
19 import org.alfresco.filesys.util.DataPacker;
20 import org.alfresco.filesys.util.HexDump;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 /**
25  * NetBIOS Packet Class
26  */

27 public class NetBIOSPacket
28 {
29     private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol.netbios");
30
31     // Minimum valid receive length
32

33     public static final int MIN_RXLEN = 4;
34
35     // NetBIOS opcodes
36

37     public static final int NAME_QUERY = 0x00;
38     public static final int NAME_REGISTER = 0x05;
39     public static final int NAME_RELEASE = 0x06;
40     public static final int WACK = 0x07;
41     public static final int REFRESH = 0x08;
42     public static final int NAME_REGISTER_MULTI = 0x0F;
43
44     public static final int RESP_QUERY = 0x10;
45     public static final int RESP_REGISTER = 0x15;
46     public static final int RESP_RELEASE = 0x16;
47
48     // NetBIOS opcode masks
49

50     public static final int MASK_OPCODE = 0xF800;
51     public static final int MASK_NMFLAGS = 0x07F0;
52     public static final int MASK_RCODE = 0x000F;
53
54     public static final int MASK_NOOPCODE = 0x07FF;
55     public static final int MASK_NOFLAGS = 0xF80F;
56     public static final int MASK_NORCODE = 0xFFF0;
57
58     public static final int MASK_RESPONSE = 0x0010;
59
60     // Flags bit values
61

62     public static final int FLG_BROADCAST = 0x0001;
63     public static final int FLG_RECURSION = 0x0008;
64     public static final int FLG_RECURSDES = 0x0010;
65     public static final int FLG_TRUNCATION = 0x0020;
66     public static final int FLG_AUTHANSWER = 0x0040;
67
68     // NetBIOS name lookup types
69

70     public static final int NAME_TYPE_NB = 0x0020;
71     public static final int NAME_TYPE_NBSTAT = 0x0021;
72
73     // RFC NetBIOS encoded name length
74

75     public static final int NAME_LEN = 32;
76
77     // NetBIOS name classes
78

79     public static final int NAME_CLASS_IN = 0x0001;
80
81     // Bit shifts for opcode/flags values
82

83     private static final int SHIFT_FLAGS = 4;
84     private static final int SHIFT_OPCODE = 11;
85
86     // Default NetBIOS buffer size to allocate
87

88     public static final int DEFAULT_BUFSIZE = 1024;
89
90     // NetBIOS packet offsets
91

92     private static final int NB_TRANSID = 0;
93     private static final int NB_OPCODE = 2;
94     private static final int NB_QDCOUNT = 4;
95     private static final int NB_ANCOUNT = 6;
96     private static final int NB_NSCOUNT = 8;
97     private static final int NB_ARCOUNT = 10;
98     private static final int NB_DATA = 12;
99
100     // NetBIOS name registration error reponse codes (RCODE field)
101

102     public static final int FMT_ERR = 0x01;
103     public static final int SRV_ERR = 0x02;
104     public static final int IMP_ERR = 0x04;
105     public static final int RFS_ERR = 0x05;
106     public static final int ACT_ERR = 0x06;
107     public static final int CFT_ERR = 0x07;
108
109     // Name flags
110

111     public static final int NAME_PERM = 0x02;
112     public static final int NAME_ACTIVE = 0x04;
113     public static final int NAME_CONFLICT = 0x08;
114     public static final int NAME_DEREG = 0x10;
115     public static final int NAME_GROUP = 0x80;
116
117     // NetBIOS packet buffer
118

119     private byte[] m_nbbuf;
120
121     // Actual used packet length
122

123     private int m_datalen;
124
125     /**
126      * Default constructor
127      */

128     public NetBIOSPacket()
129     {
130         m_nbbuf = new byte[DEFAULT_BUFSIZE];
131         m_datalen = NB_DATA;
132     }
133
134     /**
135      * Create a NetBIOS packet with the specified buffer.
136      *
137      * @param buf byte[]
138      */

139     public NetBIOSPacket(byte[] buf)
140     {
141         m_nbbuf = buf;
142         m_datalen = NB_DATA;
143     }
144
145     /**
146      * Create a NetBIOS packet with the specified buffer size.
147      *
148      * @param siz int
149      */

150     public NetBIOSPacket(int siz)
151     {
152         m_nbbuf = new byte[siz];
153         m_datalen = NB_DATA;
154     }
155
156     /**
157      * Dump the packet structure to the console.
158      *
159      * @param sessPkt True if this is a NetBIOS session packet, else false.
160      */

161     public void DumpPacket(boolean sessPkt)
162     {
163
164         // Display the transaction id
165

166         logger.debug("NetBIOS Packet Dump :-");
167
168         // Detrmine the packet type
169

170         if (sessPkt == true)
171         {
172
173             switch (getPacketType())
174             {
175
176             // NetBIOS session request
177

178             case RFCNetBIOSProtocol.SESSION_REQUEST:
179                 StringBuffer JavaDoc name = new StringBuffer JavaDoc();
180                 for (int i = 0; i < 32; i++)
181                     name.append((char) m_nbbuf[39 + i]);
182                 logger.debug("Session request from " + NetBIOSSession.DecodeName(name.toString()));
183                 break;
184
185             // NetBIOS message
186

187             case RFCNetBIOSProtocol.SESSION_MESSAGE:
188                 break;
189             }
190         }
191         else
192         {
193
194             // Display the packet type
195

196             logger.debug(" Transaction Id : " + getTransactionId());
197
198             String JavaDoc opCode = null;
199
200             switch (getOpcode())
201             {
202             case NAME_QUERY:
203                 opCode = "QUERY";
204                 break;
205             case RESP_QUERY:
206                 opCode = "QUERY (Response)";
207                 break;
208             case NAME_REGISTER:
209                 opCode = "NAME REGISTER";
210                 break;
211             case RESP_REGISTER:
212                 opCode = "NAME REGISTER (Response)";
213                 break;
214             case NAME_RELEASE:
215                 opCode = "NAME RELEASE";
216                 break;
217             case RESP_RELEASE:
218                 opCode = "NAME RELEASE (Response)";
219                 break;
220             case WACK:
221                 opCode = "WACK";
222                 break;
223             case REFRESH:
224                 opCode = "REFRESH";
225                 break;
226             default:
227                 opCode = Integer.toHexString(getOpcode());
228                 break;
229             }
230             logger.debug(" Opcode : " + opCode);
231
232             // Display the flags
233

234             logger.debug(" Flags : " + Integer.toHexString(getFlags()));
235
236             // Display the name counts
237

238             logger.debug(" QDCount : " + getQuestionCount());
239             logger.debug(" ANCount : " + getAnswerCount());
240             logger.debug(" NSCount : " + getNameServiceCount());
241             logger.debug(" ARCount : " + getAdditionalCount());
242
243             // Dump the question name, if there is one
244

245             if (getQuestionCount() > 0)
246             {
247
248                 // Get the encoded name string
249

250                 StringBuffer JavaDoc encName = new StringBuffer JavaDoc();
251                 for (int i = 1; i <= 32; i++)
252                     encName.append((char) m_nbbuf[NB_DATA + i]);
253
254                 // Decode the name
255

256                 String JavaDoc name = NetBIOSSession.DecodeName(encName.toString());
257                 logger.debug(" QName : " + name + " <" + NetBIOSName.TypeAsString(name.charAt(15)) + ">");
258             }
259         }
260
261         // Dump the raw data
262

263         logger.debug("********** Raw NetBIOS Data Dump **********");
264         HexDump.Dump(getBuffer(), getLength(), 0);
265     }
266
267     /**
268      * Get the additional byte count.
269      *
270      * @return int
271      */

272     public final int getAdditionalCount()
273     {
274         return DataPacker.getShort(m_nbbuf, NB_ARCOUNT);
275     }
276
277     /**
278      * Get the answer name details
279      *
280      * @return String
281      */

282     public final String JavaDoc getAnswerName()
283     {
284
285         // Pack the encoded name into the NetBIOS packet
286

287         return NetBIOSSession.DecodeName(m_nbbuf, NB_DATA + 1);
288     }
289
290     /**
291      * Get the answer count.
292      *
293      * @return int
294      */

295     public final int getAnswerCount()
296     {
297         return DataPacker.getShort(m_nbbuf, NB_ANCOUNT);
298     }
299
300     /**
301      * Get the answer name list
302      *
303      * @return NetBIOSNameList
304      */

305     public final NetBIOSNameList getAnswerNameList()
306     {
307
308         // Check if there are any answer names
309

310         int cnt = getAnswerCount();
311         if (cnt == 0)
312             return null;
313
314         NetBIOSNameList nameList = new NetBIOSNameList();
315         int pos = NB_DATA;
316
317         while (cnt-- > 0)
318         {
319
320             // Get a NetBIOS name from the buffer
321

322             int nameLen = NetBIOSName.decodeNetBIOSNameLength(m_nbbuf, pos);
323             NetBIOSName name = NetBIOSName.decodeNetBIOSName(m_nbbuf, pos);
324
325             // Skip the type, class and TTL
326

327             pos += nameLen;
328             pos += 8;
329
330             // Get the count of data bytes
331

332             int dataCnt = DataPacker.getShort(m_nbbuf, pos);
333             pos += 2;
334
335             while (dataCnt > 0)
336             {
337
338                 // Get the flags, check if the name is a unique or group name
339

340                 int flags = DataPacker.getShort(m_nbbuf, pos);
341                 pos += 2;
342                 if ((flags & NAME_GROUP) != 0)
343                     name.setGroup(true);
344
345                 // Get the IP address and add to the list of addresses for the current name
346

347                 byte[] ipaddr = new byte[4];
348                 for (int i = 0; i < 4; i++)
349                     ipaddr[i] = m_nbbuf[pos++];
350
351                 name.addIPAddress(ipaddr);
352
353                 // Update the data count
354

355                 dataCnt -= 6;
356             }
357
358             // Add the name to the name list
359

360             nameList.addName(name);
361         }
362
363         // Return the name list
364

365         return nameList;
366     }
367
368     /**
369      * Get the answer name list from an adapter status reply
370      *
371      * @return NetBIOSNameList
372      */

373     public final NetBIOSNameList getAdapterStatusNameList()
374     {
375
376         // Check if there are any answer names
377

378         int cnt = getAnswerCount();
379         if (cnt == 0)
380             return null;
381
382         NetBIOSNameList nameList = new NetBIOSNameList();
383         int pos = NB_DATA;
384
385         // Skip the initial name
386

387         int nameLen = (int) (m_nbbuf[pos++] & 0xFF);
388         pos += nameLen;
389         pos = DataPacker.wordAlign(pos);
390         pos += 8;
391
392         // Get the count of data bytes and name count
393

394         int dataCnt = DataPacker.getShort(m_nbbuf, pos);
395         pos += 2;
396
397         int nameCnt = (int) (m_nbbuf[pos++] & 0xFF);
398
399         while (nameCnt > 0 && dataCnt > 0)
400         {
401
402             // Get the NetBIOS name/type
403

404             NetBIOSName nbName = new NetBIOSName(m_nbbuf, pos);
405             pos += 16;
406
407             // Get the name type flags, check if this is a unique or group name
408

409             int typ = DataPacker.getShort(m_nbbuf, pos);
410             pos += 2;
411
412             if ((typ & NAME_GROUP) != 0)
413                 nbName.setGroup(true);
414
415             // Add the name to the list
416

417             nameList.addName(nbName);
418
419             // Update the data count and name count
420

421             dataCnt -= 18;
422             nameCnt--;
423         }
424
425         // Return the name list
426

427         return nameList;
428     }
429
430     /**
431      * Return the NetBIOS buffer.
432      *
433      * @return byte[]
434      */

435     public final byte[] getBuffer()
436     {
437         return m_nbbuf;
438     }
439
440     /**
441      * Get the flags from the received NetBIOS packet.
442      *
443      * @return int
444      */

445     public final int getFlags()
446     {
447         int flags = DataPacker.getShort(m_nbbuf, NB_QDCOUNT) & MASK_NMFLAGS;
448         flags = flags >> SHIFT_FLAGS;
449         return flags;
450     }
451
452     /**
453      * Return the NetBIOS header flags value.
454      *
455      * @return int
456      */

457     public final int getHeaderFlags()
458     {
459         return m_nbbuf[1] & 0x00FF;
460     }
461
462     /**
463      * Return the NetBIOS header data length value.
464      *
465      * @return int
466      */

467     public final int getHeaderLength()
468     {
469         return DataPacker.getIntelShort(m_nbbuf, 2) & 0xFFFF;
470     }
471
472     /**
473      * Return the NetBIOS header message type.
474      *
475      * @return int
476      */

477     public final int getHeaderType()
478     {
479         return m_nbbuf[0] & 0x00FF;
480     }
481
482     /**
483      * Return the received packet length.
484      *
485      * @return int
486      */

487     public final int getLength()
488     {
489         return m_datalen;
490     }
491
492     /**
493      * Return the name service count.
494      *
495      * @return int
496      */

497     public final int getNameServiceCount()
498     {
499         return DataPacker.getShort(m_nbbuf, NB_NSCOUNT);
500     }
501
502     /**
503      * Return the NetBIOS opcode.
504      *
505      * @return int
506      */

507     public final int getOpcode()
508     {
509         int op = DataPacker.getShort(m_nbbuf, NB_OPCODE) & MASK_OPCODE;
510         op = op >> SHIFT_OPCODE;
511         return op;
512     }
513
514     /**
515      * Return the NetBIOS packet type.
516      *
517      * @return int
518      */

519     public final int getPacketType()
520     {
521         return (int) (m_nbbuf[0] & 0xFF);
522     }
523
524     /**
525      * Return the question count.
526      *
527      * @return int
528      */

529     public final int getQuestionCount()
530     {
531         return DataPacker.getShort(m_nbbuf, NB_QDCOUNT);
532     }
533
534     /**
535      * Get the question name.
536      */

537     public final String JavaDoc getQuestionName()
538     {
539
540         // Pack the encoded name into the NetBIOS packet
541

542         return NetBIOSSession.DecodeName(m_nbbuf, NB_DATA + 1);
543     }
544
545     /**
546      * Get the question name length.
547      */

548     public final int getQuestionNameLength()
549     {
550
551         // Pack the encoded name into the NetBIOS packet
552

553         return (int) m_nbbuf[NB_DATA] & 0xFF;
554     }
555
556     /**
557      * Return the result code for the received packet.
558      *
559      * @return int
560      */

561     public final int getResultCode()
562     {
563         int res = DataPacker.getShort(m_nbbuf, NB_OPCODE) & MASK_RCODE;
564         return res;
565     }
566
567     /**
568      * Return the NetBIOS transaction id.
569      *
570      * @return int
571      */

572     public final int getTransactionId()
573     {
574         return DataPacker.getShort(m_nbbuf, NB_TRANSID);
575     }
576
577     /**
578      * Determine if the received packet is a repsonse packet.
579      *
580      * @return boolean
581      */

582     public final boolean isResponse()
583     {
584         if ((getOpcode() & MASK_RESPONSE) != 0)
585             return true;
586         return false;
587     }
588
589     /**
590      * Set the additional byte count.
591      *
592      * @param cnt int
593      */

594     public final void setAdditionalCount(int cnt)
595     {
596         DataPacker.putShort((short) cnt, m_nbbuf, NB_ARCOUNT);
597     }
598
599     /**
600      * Set the answer byte count.
601      *
602      * @param cnt int
603      */

604     public final void setAnswerCount(int cnt)
605     {
606         DataPacker.putShort((short) cnt, m_nbbuf, NB_ANCOUNT);
607     }
608
609     /**
610      * Set the answer name.
611      *
612      * @param name java.lang.String
613      * @param qtyp int
614      * @param qcls int
615      */

616     public final int setAnswerName(String JavaDoc name, char ntyp, int qtyp, int qcls)
617     {
618
619         // RFC encode the NetBIOS name string
620

621         String JavaDoc encName = NetBIOSSession.ConvertName(name, ntyp);
622         byte[] nameByts = encName.getBytes();
623
624         // Pack the encoded name into the NetBIOS packet
625

626         int pos = NB_DATA;
627         m_nbbuf[pos++] = (byte) NAME_LEN;
628
629         for (int i = 0; i < 32; i++)
630             m_nbbuf[pos++] = nameByts[i];
631         m_nbbuf[pos++] = 0x00;
632
633         // Set the name type and class
634

635         DataPacker.putShort((short) qtyp, m_nbbuf, pos);
636         pos += 2;
637
638         DataPacker.putShort((short) qcls, m_nbbuf, pos);
639         pos += 2;
640
641         // Set the packet length
642

643         if (pos > m_datalen)
644             setLength(pos);
645         return pos;
646     }
647
648     /**
649      * Set the flags.
650      *
651      * @param flg int
652      */

653     public final void setFlags(int flg)
654     {
655         int val = DataPacker.getShort(m_nbbuf, NB_OPCODE) & MASK_NOFLAGS;
656         val += (flg << SHIFT_FLAGS);
657         DataPacker.putShort((short) val, m_nbbuf, NB_OPCODE);
658     }
659
660     /**
661      * Set the NetBIOS packet header flags value.
662      *
663      * @param flg int
664      */

665     public final void setHeaderFlags(int flg)
666     {
667         m_nbbuf[1] = (byte) (flg & 0x00FF);
668     }
669
670     /**
671      * Set the NetBIOS packet data length in the packet header.
672      *
673      * @param len int
674      */

675     public final void setHeaderLength(int len)
676     {
677         DataPacker.putIntelShort(len, m_nbbuf, 2);
678     }
679
680     /**
681      * Set the NetBIOS packet type in the packet header.
682      *
683      * @param typ int
684      */

685     public final void setHeaderType(int typ)
686     {
687         m_nbbuf[0] = (byte) (typ & 0x00FF);
688     }
689
690     /**
691      * Set the IP address.
692      *
693      * @return int
694      * @param off int
695      * @param ipaddr byte[]
696      */

697     public final int setIPAddress(int off, byte[] ipaddr)
698     {
699
700         // Pack the IP address
701

702         for (int i = 0; i < 4; i++)
703             m_nbbuf[off + i] = ipaddr[i];
704
705         // Set the packet length
706

707         int pos = off + 4;
708         if (pos > m_datalen)
709             setLength(pos);
710
711         // Return the new packet offset
712

713         return pos;
714     }
715
716     /**
717      * Set the packet data length.
718      *
719      * @param len int
720      */

721     public final void setLength(int len)
722     {
723         m_datalen = len;
724     }
725
726     /**
727      * Set the name registration flags.
728      *
729      * @return int
730      * @param off int
731      * @param flg int
732      */

733     public final int setNameRegistrationFlags(int off, int flg)
734     {
735
736         // Set the name registration flags
737

738         DataPacker.putShort((short) 0x0006, m_nbbuf, off);
739         DataPacker.putShort((short) flg, m_nbbuf, off + 2);
740
741         // Set the packet length
742

743         int pos = off + 4;
744         if (pos > m_datalen)
745             setLength(pos);
746
747         // Return the new packet offset
748

749         return pos;
750     }
751
752     /**
753      * Set the name service count.
754      *
755      * @param cnt int
756      */

757     public final void setNameServiceCount(int cnt)
758     {
759         DataPacker.putShort((short) cnt, m_nbbuf, NB_NSCOUNT);
760     }
761
762     /**
763      * Set the NetBIOS opcode.
764      *
765      * @param op int
766      */

767     public final void setOpcode(int op)
768     {
769         int val = DataPacker.getShort(m_nbbuf, NB_OPCODE) & MASK_NOOPCODE;
770         val = val + (op << SHIFT_OPCODE);
771         DataPacker.putShort((short) val, m_nbbuf, NB_OPCODE);
772     }
773
774     /**
775      * Set the question count.
776      *
777      * @param cnt int
778      */

779     public final void setQuestionCount(int cnt)
780     {
781         DataPacker.putShort((short) cnt, m_nbbuf, NB_QDCOUNT);
782     }
783
784     /**
785      * Set the question name.
786      *
787      * @param name NetBIOSName
788      * @param qtyp int
789      * @param qcls int
790      * @return int
791      */

792     public final int setQuestionName(NetBIOSName name, int qtyp, int qcls)
793     {
794
795         // Encode the NetBIOS name
796

797         byte[] nameByts = name.encodeName();
798
799         // Pack the encoded name into the NetBIOS packet
800

801         int pos = NB_DATA;
802         System.arraycopy(nameByts, 0, m_nbbuf, pos, nameByts.length);
803         pos += nameByts.length;
804
805         // Set the name type and class
806

807         DataPacker.putShort((short) qtyp, m_nbbuf, pos);
808         pos += 2;
809
810         DataPacker.putShort((short) qcls, m_nbbuf, pos);
811         pos += 2;
812
813         // Set the packet length
814

815         if (pos > m_datalen)
816             setLength(pos);
817         return pos;
818     }
819
820     /**
821      * Set the question name.
822      *
823      * @param name java.lang.String
824      * @param qtyp int
825      * @param qcls int
826      */

827     public final int setQuestionName(String JavaDoc name, char ntyp, int qtyp, int qcls)
828     {
829
830         // RFC encode the NetBIOS name string
831

832         String JavaDoc encName = NetBIOSSession.ConvertName(name, ntyp);
833         byte[] nameByts = encName.getBytes();
834
835         // Pack the encoded name into the NetBIOS packet
836

837         int pos = NB_DATA;
838         m_nbbuf[pos++] = (byte) NAME_LEN;
839
840         for (int i = 0; i < 32; i++)
841             m_nbbuf[pos++] = nameByts[i];
842         m_nbbuf[pos++] = 0x00;
843
844         // Set the name type and class
845

846         DataPacker.putShort((short) qtyp, m_nbbuf, pos);
847         pos += 2;
848
849         DataPacker.putShort((short) qcls, m_nbbuf, pos);
850         pos += 2;
851
852         // Set the packet length
853

854         if (pos > m_datalen)
855             setLength(pos);
856         return pos;
857     }
858
859     /**
860      * Pack the resource data into the packet.
861      *
862      * @return int
863      * @param off int
864      * @param flg int
865      * @param data byte[]
866      * @param len int
867      */

868     public final int setResourceData(int off, int flg, byte[] data, int len)
869     {
870
871         // Set the resource data type
872

873         DataPacker.putShort((short) flg, m_nbbuf, off);
874
875         // Pack the data
876

877         int pos = off + 2;
878         for (int i = 0; i < len; i++)
879             m_nbbuf[pos++] = data[i];
880
881         // Set the packet length
882

883         if (pos > m_datalen)
884             setLength(pos);
885         return pos;
886     }
887
888     /**
889      * Set the resource data length in the NetBIOS packet.
890      *
891      * @return int
892      * @param off int
893      * @param len int
894      */

895     public final int setResourceDataLength(int off, int len)
896     {
897
898         // Set the resource data length
899

900         DataPacker.putShort((short) len, m_nbbuf, off);
901
902         // Set the packet length
903

904         int pos = off + 2;
905         if (pos > m_datalen)
906             setLength(pos);
907
908         // Return the new packet offset
909

910         return pos;
911     }
912
913     /**
914      * Set the resource record.
915      *
916      * @param pktoff Packet offset to pack the resource record.
917      * @param offset Offset to name.
918      * @param qtyp int
919      * @param qcls int
920      */

921     public final int setResourceRecord(int pktoff, int rroff, int qtyp, int qcls)
922     {
923
924         // Pack the resource record details
925

926         DataPacker.putShort((short) (0xC000 + rroff), m_nbbuf, pktoff);
927         DataPacker.putShort((short) qtyp, m_nbbuf, pktoff + 2);
928         DataPacker.putShort((short) qcls, m_nbbuf, pktoff + 4);
929
930         // Set the packet length
931

932         int pos = pktoff + 6;
933         if (pos > m_datalen)
934             setLength(pos);
935
936         // Return the new packet offset
937

938         return pos;
939     }
940
941     /**
942      * Set the transaction id.
943      *
944      * @param id int
945      */

946     public final void setTransactionId(int id)
947     {
948         DataPacker.putShort((short) id, m_nbbuf, NB_TRANSID);
949     }
950
951     /**
952      * Set the time to live for the packet.
953      *
954      * @return int
955      * @param off int
956      * @param ttl int
957      */

958     public final int setTTL(int off, int ttl)
959     {
960
961         // Set the time to live value for the packet
962

963         DataPacker.putInt(ttl, m_nbbuf, off);
964
965         // Set the packet length
966

967         int pos = off + 4;
968         if (pos > m_datalen)
969             setLength(pos);
970
971         // Return the new packet offset
972

973         return pos;
974     }
975
976     /**
977      * Return a packet type as a string
978      *
979      * @param typ int
980      * @return String
981      */

982     public final static String JavaDoc getTypeAsString(int typ)
983     {
984
985         // Return the NetBIOS packet type as a string
986

987         String JavaDoc typStr = "";
988
989         switch (typ)
990         {
991         case RFCNetBIOSProtocol.SESSION_ACK:
992             typStr = "SessionAck";
993             break;
994         case RFCNetBIOSProtocol.SESSION_KEEPALIVE:
995             typStr = "SessionKeepAlive";
996             break;
997         case RFCNetBIOSProtocol.SESSION_MESSAGE:
998             typStr = "SessionMessage";
999             break;
1000        case RFCNetBIOSProtocol.SESSION_REJECT:
1001            typStr = "SessionReject";
1002            break;
1003        case RFCNetBIOSProtocol.SESSION_REQUEST:
1004            typStr = "SessionRequest";
1005            break;
1006        case RFCNetBIOSProtocol.SESSION_RETARGET:
1007            typStr = "SessionRetarget";
1008            break;
1009        default:
1010            typStr = "Unknown 0x" + Integer.toHexString(typ);
1011            break;
1012        }
1013
1014        // Return the packet type string
1015

1016        return typStr;
1017    }
1018
1019    /**
1020     * Build a name query response packet for the specified NetBIOS name
1021     *
1022     * @param name NetBIOSName
1023     * @return int
1024     */

1025    public final int buildNameQueryResponse(NetBIOSName name)
1026    {
1027
1028        // Fill in the header
1029

1030        setOpcode(NetBIOSPacket.RESP_QUERY);
1031        setFlags(NetBIOSPacket.FLG_RECURSDES + NetBIOSPacket.FLG_AUTHANSWER);
1032
1033        setQuestionCount(0);
1034        setAnswerCount(1);
1035        setAdditionalCount(0);
1036        setNameServiceCount(0);
1037
1038        int pos = setAnswerName(name.getName(), name.getType(), 0x20, 0x01);
1039        pos = setTTL(pos, 10000);
1040        pos = setResourceDataLength(pos, name.numberOfAddresses() * 6);
1041
1042        // Pack the IP address(es) for this name
1043

1044        for (int i = 0; i < name.numberOfAddresses(); i++)
1045        {
1046
1047            // Get the current IP address
1048

1049            byte[] ipaddr = name.getIPAddress(i);
1050
1051            // Pack the NetBIOS flags and IP address
1052

1053            DataPacker.putShort((short) 0x00, m_nbbuf, pos);
1054            pos += 2;
1055
1056            for (int j = 0; j < 4; j++)
1057                m_nbbuf[pos++] = ipaddr[j];
1058        }
1059
1060        // Set the packet length, and return the length
1061

1062        setLength(pos);
1063        return getLength();
1064    }
1065
1066    /**
1067     * Build an add name request packet for the specified NetBIOS name
1068     *
1069     * @param name NetBIOSName
1070     * @param addrIdx int
1071     * @param tranId int
1072     * @return int
1073     */

1074    public final int buildAddNameRequest(NetBIOSName name, int addrIdx, int tranId)
1075    {
1076
1077        // Initialize an add name NetBIOS packet
1078

1079        setTransactionId(tranId);
1080        setOpcode(NetBIOSPacket.NAME_REGISTER);
1081        setFlags(NetBIOSPacket.FLG_BROADCAST + NetBIOSPacket.FLG_RECURSION);
1082
1083        setQuestionCount(1);
1084        setAnswerCount(0);
1085        setNameServiceCount(0);
1086        setAdditionalCount(1);
1087
1088        int pos = setQuestionName(name.getName(), name.getType(), 0x20, 0x01);
1089        pos = setResourceRecord(pos, 12, 0x20, 0x01);
1090
1091        if (name.getTimeToLive() == 0)
1092            pos = setTTL(pos, NetBIOSName.DefaultTTL);
1093        else
1094            pos = setTTL(pos, name.getTimeToLive());
1095
1096        short flg = 0;
1097        if (name.isGroupName())
1098            flg = (short) 0x8000;
1099        pos = setNameRegistrationFlags(pos, flg);
1100        pos = setIPAddress(pos, name.getIPAddress(addrIdx));
1101
1102        // Return the packet length
1103

1104        setLength(pos);
1105        return pos;
1106    }
1107
1108    /**
1109     * Build a refresh name request packet for the specified NetBIOS name
1110     *
1111     * @param name NetBIOSName
1112     * @param addrIdx int
1113     * @param tranId int
1114     * @return int
1115     */

1116    public final int buildRefreshNameRequest(NetBIOSName name, int addrIdx, int tranId)
1117    {
1118
1119        // Initialize an add name NetBIOS packet
1120

1121        setTransactionId(tranId);
1122        setOpcode(NetBIOSPacket.REFRESH);
1123        setFlags(NetBIOSPacket.FLG_BROADCAST + NetBIOSPacket.FLG_RECURSION);
1124
1125        setQuestionCount(1);
1126        setAnswerCount(0);
1127        setNameServiceCount(0);
1128        setAdditionalCount(1);
1129
1130        int pos = setQuestionName(name.getName(), name.getType(), 0x20, 0x01);
1131        pos = setResourceRecord(pos, 12, 0x20, 0x01);
1132
1133        if (name.getTimeToLive() == 0)
1134            pos = setTTL(pos, NetBIOSName.DefaultTTL);
1135        else
1136            pos = setTTL(pos, name.getTimeToLive());
1137
1138        short flg = 0;
1139        if (name.isGroupName())
1140            flg = (short) 0x8000;
1141        pos = setNameRegistrationFlags(pos, flg);
1142        pos = setIPAddress(pos, name.getIPAddress(addrIdx));
1143
1144        // Return the packet length
1145

1146        setLength(pos);
1147        return pos;
1148    }
1149
1150    /**
1151     * Build a delete name request packet for the specified NetBIOS name
1152     *
1153     * @param name NetBIOSName
1154     * @param addrIdx int
1155     * @param tranId int
1156     * @return int
1157     */

1158    public final int buildDeleteNameRequest(NetBIOSName name, int addrIdx, int tranId)
1159    {
1160
1161        // Initialize a delete name NetBIOS packet
1162

1163        setTransactionId(tranId);
1164        setOpcode(NetBIOSPacket.NAME_RELEASE);
1165        setFlags(NetBIOSPacket.FLG_BROADCAST + NetBIOSPacket.FLG_RECURSION);
1166
1167        setQuestionCount(1);
1168        setAnswerCount(0);
1169        setNameServiceCount(0);
1170        setAdditionalCount(1);
1171
1172        int pos = setQuestionName(name.getName(), name.getType(), 0x20, 0x01);
1173        pos = setResourceRecord(pos, 12, 0x20, 0x01);
1174        pos = setTTL(pos, 30000);
1175
1176        short flg = 0;
1177        if (name.isGroupName())
1178            flg = (short) 0x8000;
1179        pos = setNameRegistrationFlags(pos, flg);
1180        pos = setIPAddress(pos, name.getIPAddress(addrIdx));
1181
1182        // Return the packet length
1183

1184        setLength(pos);
1185        return pos;
1186    }
1187
1188    /**
1189     * Build a name quesy request packet for the specified NetBIOS name
1190     *
1191     * @param name NetBIOSName
1192     * @param tranId int
1193     * @return int
1194     */

1195    public final int buildNameQueryRequest(NetBIOSName name, int tranId)
1196    {
1197
1198        // Initialize a name query NetBIOS packet
1199

1200        setTransactionId(tranId);
1201        setOpcode(NetBIOSPacket.NAME_QUERY);
1202        setFlags(NetBIOSSession.hasWINSServer() ? 0 : NetBIOSPacket.FLG_BROADCAST);
1203        setQuestionCount(1);
1204        return setQuestionName(name, NetBIOSPacket.NAME_TYPE_NB, NetBIOSPacket.NAME_CLASS_IN);
1205    }
1206
1207    /**
1208     * Build a session setup request packet
1209     *
1210     * @param fromName NetBIOSName
1211     * @param toName NetBIOSName
1212     * @return int
1213     */

1214    public final int buildSessionSetupRequest(NetBIOSName fromName, NetBIOSName toName)
1215    {
1216
1217        // Initialize the session setup packet header
1218

1219        m_nbbuf[0] = (byte) RFCNetBIOSProtocol.SESSION_REQUEST;
1220        m_nbbuf[1] = (byte) 0; // flags
1221

1222        // Set the remote NetBIOS name
1223

1224        int pos = 4;
1225        byte[] encToName = toName.encodeName();
1226        System.arraycopy(encToName, 0, m_nbbuf, pos, encToName.length);
1227        pos += encToName.length;
1228
1229        // Set the local NetBIOS name
1230

1231        byte[] encFromName = fromName.encodeName();
1232        System.arraycopy(encFromName, 0, m_nbbuf, pos, encFromName.length);
1233        pos += encFromName.length;
1234
1235        // Set the packet length
1236

1237        setLength(pos);
1238
1239        // Set the length in the session request header
1240

1241        DataPacker.putShort((short) (pos - RFCNetBIOSProtocol.HEADER_LEN), m_nbbuf, 2);
1242
1243        // Return the packet length
1244

1245        return pos;
1246    }
1247}
Popular Tags