4 Creates C code from a table of NCP type 0x2222 packet types.
5 (And 0x3333, which are the replies, but the packets are more commonly
6 refered to as type 0x2222; the 0x3333 replies are understood to be
7 part of the 0x2222 "family")
9 Data comes from "Programmer's Guide to the NetWare Core Protocol"
10 by Steve Conner and Dianne Conner.
12 $Id: ncp2222.py,v 1.3 2000/08/09 21:24:27 deniel Exp $
14 Copyright (c) 2000 by Gilbert Ramirez <gram@xiexie.org>
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License
18 as published by the Free Software Foundation; either version 2
19 of the License, or (at your option) any later version.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 ##############################################################################
35 ##############################################################################
37 class UniqueCollection:
38 """The UniqueCollection class stores objects which can be compared to other
39 objects of the same class. If two objects in the collection are equivalent,
40 only one is stored."""
42 def __init__(self, name):
47 def Add(self, object):
48 """Add an object to the members lists, if a comparable object
49 doesn't already exist. The object that is in the member list, that is
50 either the object that was added or the comparable object that was
51 already in the member list, is returned."""
53 # Is 'object' a duplicate of some other member?
54 for member in self.members:
58 # Store object in our members list.
59 self.members.append(object)
63 "Returns the list of members."
66 def HasMember(self, object):
67 "Does the list of members contain the object?"
68 for member in self.members:
74 packets = UniqueCollection('NCP Packet Descriptions')
75 compcode_lists = UniqueCollection('Completion Code Lists')
76 ptvc_lists = UniqueCollection('PTVC Lists')
79 ##############################################################################
82 "NamedList's keep track of PTVC's and Completion Codes"
83 def __init__(self, name, list):
88 def __cmp__(self, other):
89 "Compare this NamedList to another"
91 # Python will do a deep comparison of lists within lists.
92 if self.list < other.list:
94 elif self.list > other.list:
100 "String representation"
101 return "NamedList: " + `self.list`
103 def Name(self, new_name = None):
104 "Get/Set name of list"
110 "Returns record lists"
114 "Is there no list (different from an empty list)?"
115 return self.list == None
118 "It the list empty (different from a null list)?"
119 assert(not self.Null())
127 class PTVC(NamedList):
128 """ProtoTree TVBuff Cursor List ("PTVC List") Class"""
130 def __init__(self, name, records):
133 NamedList.__init__(self, name, self.list)
135 # Make a PTVCRecord object for each list in 'records'
136 for record in records:
137 ptvc_rec = PTVCRecord(record)
139 # We can't make a PTVC list from a variable-length
140 # packet. XXX - unless it's FT_NSTRING
141 # if type(ptvc_rec.Length()) == type(()):
142 # if ptvc_rec.Field() == nstring8:
148 self.list.append(ptvc_rec)
151 def __init__(self, record):
153 self.length = record[1]
154 self.field = record[2]
157 field_length = self.field.Length()
159 if type(field_length) == type(0) and field_length > 0:
160 if field_length != self.length:
161 sys.stderr.write("Length %d does not match field length %d for field %s\n" % (self.length, field_length, self.field.Abbreviation()))
164 # Check if an endianness override is given
166 self.endianness = record[3]
168 # If no endianness was given in the record, then
169 # use the field's default endianness.
171 self.endianness = self.field.Endianness()
173 def __cmp__(self, other):
174 "Comparison operator"
175 if self.length < other.length:
177 elif self.length > other.length:
180 if self.field != other.field:
182 elif self.endianness != other.endianness:
188 "String representation"
190 if self.endianness == LE:
193 if type(self.length) == type(0):
195 return "{ &%s, %d, %s }" % (self.field.HFName(),
198 length = "PTVC_VARIABLE_LENGTH"
199 return "{ &%s, %s, %s }" % (self.field.HFName(),
210 ##############################################################################
214 def __init__(self, func_code, description, group):
216 self.func_code = func_code
217 self.description = description
220 self.request_records = None
221 self.reply_records = None
223 if not groups.has_key(group):
224 sys.stderr.write("NCP 0x%x has invalid group '%s'\n" % (self.func_code, group))
227 if self.HasSubFunction():
228 # NCP Function with SubFunction
229 self.start_offset = 10
231 # Simple NCP Function
232 self.start_offset = 7
234 def FunctionCode(self, part=None):
235 "Returns the function code for this NCP packet."
237 return self.func_code
239 if self.HasSubFunction():
240 return (self.func_code & 0xff00) >> 8
242 return self.func_code
244 if self.HasSubFunction():
245 return self.func_code & 0x00ff
249 sys.stderr.write("Unknown directive '%s' for function_code()\n" % (part))
252 def HasSubFunction(self):
253 "Does this NPC packet require a subfunction field?"
254 if self.func_code <= 0xff:
259 def Description(self):
260 return self.description
265 def PTVCRequest(self):
266 return self.ptvc_request
269 return self.ptvc_reply
271 def Request(self, size, records=[]):
272 self.request_size = size
273 self.request_records = records
274 if self.HasSubFunction():
275 self.CheckRecords(size, records, "Request", 10)
277 self.CheckRecords(size, records, "Request", 7)
278 self.ptvc_request = self.MakePTVC(records, "request")
280 def Reply(self, size, records=[]):
281 self.reply_size = size
282 self.reply_records = records
283 self.CheckRecords(size, records, "Reply", 8)
284 self.ptvc_reply = self.MakePTVC(records, "reply")
286 def CheckRecords(self, size, records, descr, min_hdr_length):
287 "Simple sanity check"
290 if type(size) == type(()):
294 lower = min_hdr_length
295 upper = min_hdr_length
297 for record in records:
301 if type(rec_size) == type(()):
302 rec_lower = rec_size[0]
303 rec_upper = rec_size[1]
305 lower = lower + rec_lower
306 upper = upper + rec_upper
310 sys.stderr.write("%s records for 2222/0x%x sum to %d bytes minimum, but param1 shows %d\n" \
311 % (descr, self.FunctionCode(), lower, min))
314 sys.stderr.write("%s records for 2222/0x%x sum to %d bytes maximum, but param1 shows %d\n" \
315 % (descr, self.FunctionCode(), upper, max))
322 def MakePTVC(self, records, name_suffix):
323 """Makes a PTVC out of a request or reply record list. Possibly adds
324 it to the global list of PTVCs (the global list is a UniqueCollection,
325 so an equivalent PTVC may already be in the global list)."""
327 name = "%s_%s" % (self.CName(), name_suffix)
328 ptvc = PTVC(name, records)
329 return ptvc_lists.Add(ptvc)
332 "Returns a C symbol based on the NCP function code"
333 return "ncp_0x%x" % (self.func_code)
336 """Returns a list of variables used in the request and reply records.
337 A variable is listed only once, even if it is used twice (once in
338 the request, once in the reply)."""
341 if self.request_records:
342 for record in self.request_records:
346 if self.reply_records:
347 for record in self.reply_records:
351 return variables.keys()
354 def CompletionCodes(self, codes=None):
355 """Sets or returns the list of completion codes. Internally, a NamedList
356 is used to store the completion codes, but the caller of this function
357 never realizes that because Python lists are the input and output."""
365 if not errors.has_key(code):
366 sys.stderr.write("Errors table does not have key 0x%04x for NCP=0x%x\n" % (code,
370 # Delay the exit until here so that the programmer can get the complete
371 # list of missing error codes
375 # Create CompletionCode (NamedList) object and possible add it to
376 # the global list of completion code lists.
377 name = "%s_errors" % (self.CName())
379 codes_list = NamedList(name, codes)
380 self.codes = compcode_lists.Add(codes_list)
385 """Adds the NCP object to the global collection of NCP objects. This
386 is done automatically after setting the CompletionCode list. Yes, this
387 is a shortcut, but it makes our list of NCP packet definitions look
388 neater, since an explicit "add to global list of packets" is not needed."""
390 # Add packet to global collection of packets
391 if packets.HasMember(self):
392 sys.stderr.write("Already have NCP Function Code 0x%x\n" % \
400 ##############################################################################
402 LE = 1 # Little-Endian
404 NA = -1 # Not Applicable
407 " Virtual class for NCP field types"
414 def __init__(self, abbrev, descr, bytes, endianness = NA):
422 def Abbreviation(self):
425 def Description(self):
429 return "hf_ncp_" + self.abbrev
432 return "ncp." + self.abbrev
434 def EtherealFType(self):
437 def Display(self, newval=None):
442 def ValuesName(self):
448 def Endianness(self):
449 return self.endianness
454 def __init__(self, abbrev, descr):
455 Type.__init__(self, abbrev, descr, 1)
457 # Same as above. Both are provided for convenience
461 def __init__(self, abbrev, descr):
462 Type.__init__(self, abbrev, descr, 1)
467 def __init__(self, abbrev, descr, endianness = BE):
468 Type.__init__(self, abbrev, descr, 2, endianness)
473 def __init__(self, abbrev, descr, endianness = BE):
474 Type.__init__(self, abbrev, descr, 4, endianness)
476 class nstring8(Type):
477 """A string of up to 255 characters. The first byte
478 gives the string length. Thus, the total length of
479 this data structure is from 1 to 256 bytes, including
483 ftype = "FT_NSTRING_UINT8"
484 def __init__(self, abbrev, descr):
485 Type.__init__(self, abbrev, descr, -1)
488 "NUL-terminated string."
492 def __init__(self, abbrev, descr):
493 Type.__init__(self, abbrev, descr, -1)
495 class val_string(Type):
496 """Abstract class for val_stringN, where N is number
497 of bits that key takes up."""
502 def __init__(self, abbrev, descr, val_string_array, endianness = BE):
503 Type.__init__(self, abbrev, descr, self.bytes, endianness)
504 self.values = val_string_array
507 result = "static const value_string %s[] = {\n" \
508 % (self.ValuesCName())
509 for val_record in self.values:
510 value = val_record[0]
512 value_repr = self.value_format % value
513 result = result + '\t{ %s,\t"%s" },\n' \
516 value_repr = self.value_format % 0
517 result = result + "\t{ %s,\tNULL },\n" % (value_repr)
518 result = result + "};\n"
522 def ValuesCName(self):
523 return "ncp_%s_vals" % (self.abbrev)
525 def ValuesName(self):
526 return "VALS(%s)" % (self.ValuesCName())
528 class val_string8(val_string):
532 value_format = "0x%02x"
534 class val_string16(val_string):
535 type = "val_string16"
538 value_format = "0x%04x"
544 def __init__(self, abbrev, descr, bytes):
545 Type.__init__(self, abbrev, descr, bytes, NA)
550 # def __init__(self, abbrev, descr):
551 # Type.__init__(self, abbrev, descr, -1)
553 # def length_var(self, length_var):
554 # self.length_var = length_var
556 ##############################################################################
557 # NCP Field Types. Defined in Appendix A of "Programmer's Guide..."
558 ##############################################################################
559 BufferSize = uint16("buffer_size", "Buffer Size")
560 ConnectionNumber = uint32("connection_number", "Connection Number")
561 DirHandle = byte("dir_handle", "Directory Handle")
563 FileHandle = bytes("file_handle", "File Handle", 6)
565 FileLock = val_string8("file_lock", "File Lock", [
566 [ 0x00, "Not Locked" ],
567 [ 0xfe, "Locked by file lock" ],
571 FileOffset = uint32("file_offset", "File Offset")
572 FilePath = nstring8("file_path", "File Path")
573 FileSize = uint32("file_size", "File Size")
574 JobType = uint16("job_type", "Job Type")
576 LogicalLockType = val_string8("logical_lock_type", "Logical Lock Type", [
577 [ 0x00, "Log file" ],
578 [ 0x01, "Log and lock file for exclusive read/write use" ],
579 [ 0x03, "Log and lock with shareable read-only use" ],
582 LogicalRecordName = nstring8("logical_record_name", "Logical Record Name")
583 LogLockType = byte("log_lock_type", "Log Lock Type")
585 MaxBytes = uint16("max_bytes", "Maximum Number of Bytes")
586 NumBytes = uint16("num_bytes", "Number of Bytes")
588 ObjectFlags = val_string8("object_flags", "Object Flags", [
589 [ 0x00, "Dynamic object" ],
590 [ 0x01, "Static object" ],
593 ObjectHasProperties = val_string8("object_has_properites", "Object Has Properties", [
594 [ 0x00, "No properties" ],
595 [ 0xff, "One or more properties" ],
598 ObjectID = uint32("object_id", "Object ID")
599 ObjectID.Display('BASE_HEX')
601 ObjectName = nstring8("object_name", "Object Name")
602 ObjectNameZ = stringz("object_nameZ", "Object Name")
604 ObjectSecurity = val_string8("object_security", "Object Security", [
605 [ 0x00, "Anyone can read or modify the object" ],
606 [ 0x01, "Client logged into the file server can read the object" ],
607 [ 0x02, "Client logged into the file server with the object's name, type and password can read the object" ],
608 [ 0x03, "Client with supervisor equivalence can read the object" ],
609 [ 0x04, "Only the operating system can read the object" ],
610 [ 0x10, "Client logged into the file server can modify the object" ],
611 [ 0x20, "Client logged into the file server with the object's name, type and password can modify the object" ],
612 [ 0x30, "Client with supervisor equivalence can modify the object" ],
613 [ 0x40, "Only the operating system can modify the object" ],
616 ObjectType = val_string16("object_type", "Object Type", [
617 [ 0x0000, "Unknown" ],
619 [ 0x0002, "User group" ],
620 [ 0x0003, "Print queue" ],
621 [ 0x0004, "NetWare file server" ],
622 [ 0x0005, "Job server" ],
623 [ 0x0006, "Gateway" ],
624 [ 0x0007, "Print server" ],
625 [ 0x0008, "Archive queue" ],
626 [ 0x0009, "Archive server" ],
627 [ 0x000a, "Job queue" ],
628 [ 0x000b, "Administration" ],
629 [ 0x0021, "NAS SNA gateway" ],
630 [ 0x0026, "Remote bridge server" ],
631 [ 0x0027, "TCP/IP gateway" ],
634 PropertyHasMoreSegments = val_string8("property_has_more_segments",
635 "Property Has More Segments", [
636 [ 0x00, "Is last segment" ],
637 [ 0xff, "More segments are available" ],
640 PropertyName = nstring8("property_name", "Property Name")
641 PropertyData = bytes("property_data", "Property Data", 128)
642 PropertySegment = uint8("property_segment", "Property Segment")
644 PropertyType = val_string8("property_type", "Property Type", [
645 [ 0x00, "Static item" ],
646 [ 0x01, "Dynamic item" ],
647 [ 0x02, "Static set" ],
648 [ 0x03, "Dynamic set" ],
651 TaskNumber = uint32("task_number", "Task Number")
652 TimeoutLimit = uint16("timeout_limit", "Timeout Limit")
653 UnknownByte = byte("unknown_byte", "Unknown Byte")
656 ##############################################################################
658 ##############################################################################
660 groups['accounting'] = "Accounting"
661 groups['afp'] = "AFP"
662 groups['auditing'] = "Auditing"
663 groups['bindery'] = "Bindery"
664 groups['connection'] = "Connection"
665 groups['directory'] = "Directory"
666 groups['extended'] = "Extended Attribute"
667 groups['file'] = "File"
668 groups['fileserver'] = "File Server"
669 groups['message'] = "Message"
670 groups['migration'] = "Data Migration"
671 groups['misc'] = "Miscellaneous"
672 groups['name'] = "Name Space"
673 groups['nds'] = "NetWare Directory"
674 groups['print'] = "Print"
675 groups['queue'] = "Queue"
676 groups['sync'] = "Synchronization"
677 groups['tss'] = "Transaction Tracking"
679 ##############################################################################
681 ##############################################################################
683 errors[0x0000] = "Ok"
684 errors[0x0001] = "Transaction tracking is available"
685 errors[0x0002] = "Ok. The data has been written"
687 errors[0x0100] = "One or more of the ConnectionNumbers in the send list are invalid"
688 errors[0x0101] = "Invalid space limit"
689 errors[0x0102] = "Insufficient disk space"
690 errors[0x0103] = "Queue server cannot add jobs"
691 errors[0x0104] = "Out of disk space"
692 errors[0x0105] = "Semaphore overflow"
694 errors[0x0200] = "One or more clients in the send list are not logged in"
695 errors[0x0201] = "Queue server cannot attach"
697 errors[0x0300] = "One or more clients in the send list are not accepting messages"
699 errors[0x0400] = "Client already has message"
700 errors[0x0401] = "Queue server cannot service job"
702 errors[0x7e00] = "NCP failed boundary check"
704 errors[0x8000] = "Lock fail"
705 errors[0x8100] = "A file handle could not be allocated by the file server"
706 errors[0x8200] = "Unauthorized to open the file"
707 errors[0x8300] = "Unable to read/write the volume. Possible bad sector on the file server"
709 errors[0x8400] = "Unauthorized to create the directory"
710 errors[0x8401] = "Unauthorized to create the file"
712 errors[0x8500] = "Unauthorized to delete the specified file"
713 errors[0x8501] = "Unauthorized to overwrite an existing file in this directory"
715 errors[0x8700] = "An unexpected character was encountered in the filename"
716 errors[0x8800] = "Invalid file handle"
717 errors[0x8900] = "Unauthorized to search this directory"
718 errors[0x8a00] = "Unauthorized to delete this directory"
719 errors[0x8b00] = "Unauthorized to rename a file in this directory"
721 errors[0x8c00] = "No set privileges"
722 errors[0x8c01] = "Unauthorized to modify a file in this directory"
723 errors[0x8c02] = "Unauthorized to change the restriction on this volume"
725 errors[0x8d00] = "Some of the affected files are in use by another client"
726 errors[0x8d01] = "The affected file is in use"
728 errors[0x8e00] = "All of the affected files are in use by another client"
729 errors[0x8f00] = "Some of the affected files are read-only"
731 errors[0x9000] = "An attempt to modify a read-only volume occurred"
732 errors[0x9001] = "All of the affected files are read-only"
734 errors[0x9100] = "Some of the affected files already exist"
736 errors[0x9200] = "Directory with the new name already exists"
737 errors[0x9201] = "All of the affected files already exist"
739 errors[0x9300] = "Unauthorized to read from this file"
740 errors[0x9400] = "Unauthorized to write to this file"
741 errors[0x9500] = "The affected file is detached"
743 errors[0x9600] = "The file server has run out of memory to service this request"
744 errors[0x9601] = "No alloc space for message"
746 errors[0x9800] = "The affected volume is not mounted"
747 errors[0x9801] = "The volume associated with VolumeNumber is not mounted"
748 errors[0x9802] = "The resulting voume does not exist"
749 errors[0x9803] = "The destination volume is not mounted"
751 errors[0x9900] = "The file server has run out of directory space on the affected volume"
752 errors[0x9a00] = "The request attempted to rename the affected file to another volume"
754 errors[0x9b00] = "DirHandle is not associated with a valid directory path"
755 errors[0x9b01] = "A resulting directory handle is not associated with a valid directory path"
756 errors[0x9b02] = "The directory associated with DirHandle does not exist"
757 errors[0x9b03] = "Bad directory handle"
759 errors[0x9c00] = "The resulting path is not valid"
760 errors[0x9c01] = "The resulting file path is not valid"
761 errors[0x9c02] = "The resulting directory path is not valid"
762 errors[0x9c03] = "Invalid path"
764 errors[0x9d00] = "A directory handle was not available for allocation"
766 errors[0x9e00] = "The name of the directory does not conform to a legal name for this name space"
767 errors[0x9e01] = "The new directory name does not conform to a legal name for this name space"
769 errors[0x9f00] = "The request attempted to delete a directory that is in use by another client"
771 errors[0xa000] = "The request attempted to delete a directory that is not empty"
772 errors[0xa100] = "An unrecoverable error occured on the affected directory"
773 errors[0xa200] = "The request attempted to read from a file region that is physically locked"
774 errors[0xa400] = "Invalid directory rename attempted"
776 errors[0xbf00] = "Requests for this name space are not valid on this volume"
778 errors[0xc000] = "Unauthorized to retrieve accounting data"
779 errors[0xc100] = "The ACCOUNT_BALANCE property does not exist"
780 errors[0xc200] = "The object has exceeded its credit limit"
781 errors[0xc300] = "Too many holds have been placed against this account"
782 errors[0xc400] = "The client account has been disabled"
784 errors[0xc500] = "Access to the account has been denied because of intruder detection"
785 errors[0xc501] = "Login lockout"
787 errors[0xc600] = "The caller does not have operator priviliges"
788 errors[0xc601] = "The client does not have operator priviliges"
790 errors[0xd000] = "Queue error"
791 errors[0xd100] = "The queue does not exist"
793 errors[0xd200] = "A queue server is not associated with this queue"
794 errors[0xd201] = "A queue server is not associated with the selected queue"
795 errors[0xd202] = "No queue server"
797 errors[0xd300] = "No queue rights"
799 errors[0xd400] = "The queue is full and cannot accept another request"
800 errors[0xd401] = "The queue associated with ObjectId is full and cannot accept another request"
802 errors[0xd500] = "A job does not exist in this queue"
803 errors[0xd501] = "No queue job"
804 errors[0xd502] = "The job associated with JobNumber does not exist in this queue"
806 errors[0xd600] = "The file server does not allow unencrypted passwords"
807 errors[0xd601] = "No job right"
809 errors[0xd700] = "Bad account"
810 errors[0xd701] = "The old and new password strings are identical"
811 errors[0xd702] = "The job is currently being serviced"
812 errors[0xd703] = "The queue is currently servicing a job"
813 errors[0xd704] = "Queue servicing"
815 errors[0xd800] = "Queue not active"
817 errors[0xd900] = "The file server cannot accept another connection as it has reached its limit"
818 errors[0xd901] = "The client is not security equivalent to one of the objects in the Q_SERVERS group property of the target queue"
819 errors[0xd902] = "Station is not a server"
821 errors[0xda00] = "Attempted to login to the file server during a restricted time period"
822 errors[0xda01] = "Queue halted"
824 errors[0xdb00] = "Attempted to login to the file server from an unauthorized workstation or network"
825 errors[0xdb01] = "The queue cannot attach another queue server"
826 errors[0xdb02] = "Maximum queue servers"
828 errors[0xde00] = "Attempted to login to the file server with an incorrect password"
829 errors[0xdf00] = "Attempted to login to the file server with a password that has expired"
831 errors[0xe700] = "No disk track"
832 errors[0xe800] = "Write to group"
833 errors[0xe900] = "The object is already a member of the group property"
835 errors[0xea00] = "No such member"
836 errors[0xea01] = "The bindery object is not a member of the set"
837 errors[0xea02] = "Non-existent member"
839 errors[0xeb00] = "The property is not a set property"
841 errors[0xec00] = "No such set"
842 errors[0xec01] = "The set property does not exist"
844 errors[0xed00] = "Property exists"
845 errors[0xed01] = "The property already exists"
846 errors[0xed02] = "An attempt was made to create a bindery object property that already exists"
848 errors[0xee00] = "The object already exists"
849 errors[0xee01] = "The bindery object already exists"
851 errors[0xef00] = "Illegal name"
852 errors[0xef01] = "Illegal characters in ObjectName field"
853 errors[0xef02] = "Invalid name"
855 errors[0xf000] = "A wildcard was detected in a field that does not support wildcards"
856 errors[0xf001] = "An illegal wildcard was detected in ObjectName"
858 errors[0xf100] = "The client does not have the rights to access this bindery object"
859 errors[0xf101] = "Bindery security"
860 errors[0xf102] = "Invalid bindery security"
862 errors[0xf200] = "Unauthorized to read from this object"
863 errors[0xf300] = "Unauthorized to rename this object"
865 errors[0xf400] = "Unauthorized to delete this object"
866 errors[0xf401] = "No object delete privileges"
867 errors[0xf402] = "Unauthorized to delete this queue"
869 errors[0xf500] = "Unauthorized to create this object"
870 errors[0xf501] = "No object create"
872 errors[0xf600] = "No property delete"
873 errors[0xf601] = "Unauthorized to delete the property of this object"
874 errors[0xf602] = "Unauthorized to delete this property"
876 errors[0xf700] = "Unauthorized to create this property"
877 errors[0xf701] = "No property create privilege"
879 errors[0xf800] = "Unauthorized to write to this property"
880 errors[0xf900] = "Unauthorized to read this property"
881 errors[0xfa00] = "Temporary remap error"
883 errors[0xfb00] = "No such property"
884 errors[0xfb01] = "The file server does not support this request"
885 errors[0xfb02] = "The specified property does not exist"
886 errors[0xfb03] = "The PASSWORD property does not exist for this bindery object"
888 errors[0xfc00] = "The message queue cannot accept another message"
889 errors[0xfc01] = "The trustee associated with ObjectId does not exist"
890 errors[0xfc02] = "The specified bindery object does not exist"
891 errors[0xfc03] = "The bindery object associated with ObjectID does not exist"
892 errors[0xfc04] = "A bindery object does not exist that matches"
893 errors[0xfc05] = "The specified queue does not exist"
894 errors[0xfc06] = "No such object"
895 errors[0xfc07] = "The queue associated with ObjectID does not exist"
897 errors[0xfd00] = "Bad station number"
898 errors[0xfd01] = "The connection associated with ConnectionNumber is not active"
899 errors[0xfd02] = "Lock collision"
900 errors[0xfd03] = "Transacktion tracking is disabled"
902 errors[0xfe00] = "I/O failure"
903 errors[0xfe01] = "The files containing the bindery on the file server are locked"
904 errors[0xfe02] = "A file with the specified name already exists in this directory"
905 errors[0xfe03] = "No more restrictions were found"
906 errors[0xfe04] = "The file server was unable to lock the file within the specified time limit"
907 errors[0xfe05] = "The file server was unable to lock all files within the specified time limit"
908 errors[0xfe06] = "The bindery object associated with ObjectID is not a valid trustee"
909 errors[0xfe07] = "Directory locked"
910 errors[0xfe08] = "Bindery locked"
911 errors[0xfe09] = "Invalid semaphore name length"
912 errors[0xfe0a] = "The file server was unable to complete the operation within the specified time limit"
913 errors[0xfe0b] = "Transaction restart"
915 errors[0xff00] = "Failure"
916 errors[0xff01] = "Lock error"
917 errors[0xff02] = "File not found"
918 errors[0xff03] = "The file not found or cannot be unlocked"
919 errors[0xff04] = "Record not found"
920 errors[0xff05] = "The logical record was not found"
921 errors[0xff06] = "The printer associated with PrinterNumber does not exist"
922 errors[0xff07] = "No such printer"
923 errors[0xff08] = "Unable to complete the request"
924 errors[0xff09] = "Unauthorized to change privileges of this trustee"
925 errors[0xff0a] = "No files matching the search criteria were found"
926 errors[0xff0b] = "A file matching the search criteria was not found"
927 errors[0xff0c] = "Verification failed"
928 errors[0xff0d] = "Object associated with ObjectID is not a manager"
929 errors[0xff0e] = "Invalid initial semaphore value"
930 errors[0xff0f] = "The semaphore handle is not valid"
931 errors[0xff10] = "SemaphoreHandle is not associated with a valid sempahore"
932 errors[0xff11] = "Invalid semaphore handle"
933 errors[0xff12] = "Transaction tracking is not available"
934 errors[0xff13] = "The transaction has not yet been written to disk"
935 errors[0xff14] = "Directory already exists"
936 errors[0xff15] = "The file already exists and the deletion flag was not set"
937 errors[0xff16] = "No matching files or directories were found"
938 errors[0xff17] = "A file or directory matching the search criteria was not found"
939 errors[0xff18] = "The file already exists"
940 errors[0xff19] = "No files found"
942 ##############################################################################
944 ##############################################################################
946 pkt = NCP(0x02, "File Release Lock", 'sync')
949 pkt.CompletionCodes([0x0000, 0xff00])
955 #pkt = NCP(0x03, "Log File", 'sync')
956 #pkt.request( (12, 267), [
957 # [ 7, 1, DirHandle ],
958 # [ 8, 1, LogLockType ],
959 # [ 9, 2, TimeoutLimit, LE ],
960 # [ 11, (1, 256), FilePath ],
962 #pkt.completion_codes([0x0000, 0x8200, 0x9600, 0xfe00, 0xff01])
965 #pkt = NCP(0x04, "Lock File Set", 'sync')
967 # [ 7, TimeoutLimit ],
969 #pkt.completion_codes([0xfe, 0xff01])
972 #pkt = NCP(0x05, "Release File", 'sync')
977 #pkt.completion_codes([0x7e, 0x98, 0x9b, 0x9c, 0xff02])
980 #pkt = NCP(0x06, "Release File Set", 'sync')
982 # [ 7, UnknownByte ],
984 #pkt.completion_codes()
987 #pkt = NCP(0x07, "Clear File", 'sync')
992 #pkt.completion_codes([0x7e, 0x96, 0x98, 0x9b, 0x9c,
996 #pkt = NCP(0x08, "Clear File Set", 'sync')
1000 #pkt.completion_codes([0x7e])
1003 #pkt = NCP(0x09, "Log Logical Record", 'sync')
1005 # [ 7, LogicalLockType ],
1006 # [ 8, TimeoutLimit_be ],
1007 # [ 10, LogicalRecordName ],
1009 #pkt.completion_codes([0x96, 0xfe, 0xff])
1012 #pkt = NCP(0x0a, "Lock Logical Record Set", 'sync')
1014 # [ 7, LogicalLockType ],
1015 # [ 8, TimeoutLimit_le ],
1017 #pkt.completion_codes([0xfe, 0xff])
1020 #pkt = NCP(0x0b, "Clear Logical Record", 'sync')
1022 # [7, LogicalRecordName ],
1024 #pkt.completion_codes([0xff]
1032 #pkt = NCP(0x1100, "Lock Logical Record Set", 'sync')
1034 # [ 10, var_length_data("data").length_var("packetlength") ]
1036 #pkt.completion_codes()
1040 pkt = NCP(0x1735, "Get Bindery Object ID", 'bindery')
1041 pkt.Request((13,60), [
1042 [ 10, 2, ObjectType ],
1043 [ 12, (1,48), ObjectName ],
1047 [ 12, 2, ObjectType ],
1048 [ 14, 48, ObjectName ], # XXX
1050 pkt.CompletionCodes([0x0000, 0x9600, 0xef01, 0xf000, 0xfc02,
1054 pkt = NCP(0x1737, "Scan Bindery Object", 'bindery')
1055 pkt.Request((17,64), [
1056 [ 10, 4, ObjectID ],
1057 [ 14, 2, ObjectType ],
1058 [ 12, (1,48), ObjectName ],
1062 [ 12, 2, ObjectType ],
1063 [ 14, 48, ObjectNameZ ], # XXX
1064 [ 62, 1, ObjectFlags ],
1065 [ 63, 1, ObjectSecurity ],
1066 [ 64, 1, ObjectHasProperties ],
1068 pkt.CompletionCodes([0x0000, 0x9600, 0xef01, 0xfc02,
1072 pkt = NCP(0x173D, "Read Property Value", 'bindery')
1073 pkt.Request((15,77), [
1074 [ 10, 2, ObjectType ],
1075 [ 12, (1,48), ObjectName ],
1076 [ -1, 1, PropertySegment ],
1077 [ -1, (1,16), PropertyName ],
1080 [ 8, 128, PropertyData ],
1081 [ 136, 1, PropertyHasMoreSegments ],
1082 [ 137, 1, PropertyType ],
1084 pkt.CompletionCodes([0x0000, 0x8800, 0x9300, 0x9600, 0xec01,
1085 0xf000, 0xf100, 0xf900, 0xfb02, 0xfc02, 0xfe01, 0xff00 ])
1088 pkt = NCP(0x177C, "Service Queue Job", 'queue')
1090 [ 10, 4, ObjectID ],
1093 pkt.Reply(24, [ # XXX - 76, [
1094 [ 8, 4, ConnectionNumber ],
1095 [ 12, 4, TaskNumber ],
1096 [ 16, 4, ObjectID ],
1097 [ 20, 4, ObjectID ],
1100 # These completion codes are not documented, but guessed.
1101 pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd201, 0xd300,
1102 0xd401, 0xd502, 0xd601, 0xd704, 0xd800, 0xd901, 0xda01, 0xdb01,
1106 pkt = NCP(0x18, "End of Job", 'connection')
1109 pkt.CompletionCodes([0x0000])
1112 pkt = NCP(0x19, "Logout", 'connection')
1115 pkt.CompletionCodes([0x0000])
1118 pkt = NCP(0x21, "Negotiate Buffer Size", 'connection')
1120 [ 7, 2, BufferSize ],
1123 [ 8, 2, BufferSize ],
1125 pkt.CompletionCodes([0x0000])
1128 pkt = NCP(0x42, "Close File", 'file')
1130 [ 7, 6, FileHandle ],
1133 pkt.CompletionCodes([0x0000, 0xff00])
1136 pkt = NCP(0x47, "Get Current Size of File", 'file')
1138 [ 7, 6, FileHandle ],
1143 pkt.CompletionCodes([0x0000, 0x8800])
1146 pkt = NCP(0x48, "Read From A File", 'file')
1148 [ 7, 1, UnknownByte ],
1149 [ 8, 6, FileHandle ],
1150 [ 14, 4, FileOffset ], # my nomenclature
1151 [ 18, 2, MaxBytes ], # my nomenclature
1153 pkt.Reply(10, [ # XXX - (10,-1), [
1154 [ 8, 2, NumBytes ], # my nomenclature
1157 pkt.CompletionCodes([0x0000, 0x8800, 0x9300, 0xff00])
1159 # 2222/5701 - no info
1160 # 2222/5702 - no info
1161 # 2222/5706 - no info
1162 # 2222/5714 - no info
1166 ##############################################################################
1168 ##############################################################################
1169 if __name__ == '__main__':
1171 print " * Generated automatically from %s" % (sys.argv[0])
1172 print " * Do not edit this file manually, as all changes will be lost."
1177 * This program is free software; you can redistribute it and/or
1178 * modify it under the terms of the GNU General Public License
1179 * as published by the Free Software Foundation; either version 2
1180 * of the License, or (at your option) any later version.
1182 * This program is distributed in the hope that it will be useful,
1183 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1184 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1185 * GNU General Public License for more details.
1187 * You should have received a copy of the GNU General Public License
1188 * along with this program; if not, write to the Free Software
1189 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1192 #ifdef HAVE_CONFIG_H
1193 # include "config.h"
1198 #include "conversation.h"
1199 #include "ptvcursor.h"
1200 #include "packet-ncp-int.h"
1202 static int hf_ncp_func = -1;
1203 static int hf_ncp_length = -1;
1204 static int hf_ncp_subfunc = -1;
1205 static int hf_ncp_completion_code = -1;
1206 static int hf_ncp_connection_status = -1;
1209 # Look at all packet types in the packets collection, and cull information
1212 for packet in packets.Members():
1213 packet_keys.append(packet.FunctionCode())
1216 errors_used_list = []
1217 errors_used_hash = {}
1218 groups_used_list = []
1219 groups_used_hash = {}
1220 variables_used_hash = {}
1222 for pkt in packets.Members():
1223 # Determine which error codes are used.
1224 codes = pkt.CompletionCodes()
1225 for code in codes.Records():
1226 if not errors_used_hash.has_key(code):
1227 errors_used_hash[code] = len(errors_used_list)
1228 errors_used_list.append(code)
1230 # Determine which groups are used.
1232 if not groups_used_hash.has_key(group):
1233 groups_used_hash[group] = len(groups_used_list)
1234 groups_used_list.append(group)
1236 # Determine which variables are used.
1237 vars = pkt.Variables()
1239 variables_used_hash[var] = 1
1243 # Print the hf variable declarations
1244 for var in variables_used_hash.keys():
1245 print "static int " + var.HFName() + " = -1;"
1248 # Print the value_string's
1249 for var in variables_used_hash.keys():
1250 if var.type == "val_string8" or var.type == "val_string16":
1257 proto_register_ncp2222(void)
1260 static hf_register_info hf[] = {
1262 { "Function", "ncp.func", FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
1265 { "Packet Length", "ncp.length", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
1268 { "SubFunction", "ncp.subfunc", FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
1270 { &hf_ncp_completion_code,
1271 { "Completion Code", "ncp.completion_code", FT_UINT8, BASE_HEX, NULL, 0x0, "" }},
1273 { &hf_ncp_connection_status,
1274 { "Connection Status", "ncp.connection_status", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1277 # Print the registration code for the hf variables
1278 for var in variables_used_hash.keys():
1279 print "\t{ &%s," % (var.HFName())
1280 print "\t{ \"%s\", \"%s\", %s, %s, %s, 0x%x, \"\" }},\n" % \
1281 (var.Description(), var.DFilter(),
1282 var.EtherealFType(), var.Display(), var.ValuesName(),
1287 proto_register_field_array(proto_ncp, hf, array_length(hf));
1292 # Determine which error codes are not used
1293 errors_not_used = {}
1294 # Copy the keys from the error list...
1295 for code in errors.keys():
1296 errors_not_used[code] = 1
1297 # ... and remove the ones that *were* used.
1298 for code in errors_used_list:
1299 del errors_not_used[code]
1301 # Print a remark showing errors not used
1302 list_errors_not_used = errors_not_used.keys()
1303 list_errors_not_used.sort()
1304 for code in list_errors_not_used:
1305 print "/* Error 0x%04x not used: %s */" % (code, errors[code])
1308 # Print the errors table
1309 print "/* Error strings. */"
1310 print "static const char *ncp_errors[] = {"
1311 for code in errors_used_list:
1312 print '\t/* %02d (0x%04x) */ "%s",' % (errors_used_hash[code], code, errors[code])
1318 # Determine which groups are not used
1319 groups_not_used = {}
1320 # Copy the keys from the group list...
1321 for group in groups.keys():
1322 groups_not_used[group] = 1
1323 # ... and remove the ones that *were* used.
1324 for group in groups_used_list:
1325 del groups_not_used[group]
1327 # Print a remark showing groups not used
1328 list_groups_not_used = groups_not_used.keys()
1329 list_groups_not_used.sort()
1330 for group in list_groups_not_used:
1331 print "/* Group not used: %s = %s */" % (group, groups[group])
1334 # Print the groups table
1335 print "/* Group strings. */"
1336 print "static const char *ncp_groups[] = {"
1337 for group in groups_used_list:
1338 print '\t/* %02d (%s) */ "%s",' % (groups_used_hash[group], group, groups[group])
1342 print "/* PTVC records. These are re-used to save space. */"
1343 for ptvc in ptvc_lists.Members():
1344 if not ptvc.Null() and not ptvc.Empty():
1345 print "static const ptvc_record %s[] = {" % (ptvc.Name())
1346 records = ptvc.Records()
1347 for ptvc_rec in records:
1348 print "\t%s," % (ptvc_rec)
1349 print "\t{ NULL, 0, 0 }"
1352 # Print error_equivalency tables
1353 print "/* Error-Equivalency Tables. These are re-used to save space. */"
1354 for compcodes in compcode_lists.Members():
1355 errors = compcodes.Records()
1356 # Make sure the record for error = 0x00 comes last.
1357 print "static const error_equivalency %s[] = {" % (compcodes.Name())
1358 for error in errors:
1359 error_in_packet = error >> 8;
1360 ncp_error_index = errors_used_hash[error]
1361 print "\t{ 0x%02x, %d }, /* 0x%04x */" % (error_in_packet,
1362 ncp_error_index, error)
1363 print "\t{ 0x00, -1 }\n};\n"
1366 # Print ncp_record packet records
1367 print "#define SUBFUNC 0xff"
1368 print "#define NOSUB 0x00"
1370 print "/* ncp_record structs for packets */"
1371 print "static const ncp_record ncp_packets[] = {"
1372 for pkt in packets.Members():
1373 if pkt.HasSubFunction():
1374 subfunc_string = "SUBFUNC"
1376 subfunc_string = "NOSUB"
1377 print '\t{ 0x%02x, 0x%02x, %s, "%s",' % (pkt.FunctionCode('high'),
1378 pkt.FunctionCode('low'), subfunc_string, pkt.Description()),
1380 print '\t%d /* %s */,' % (groups_used_hash[pkt.Group()], pkt.Group())
1382 ptvc = pkt.PTVCRequest()
1383 if not ptvc.Null() and not ptvc.Empty():
1384 ptvc_request = ptvc.Name()
1386 ptvc_request = 'NULL'
1388 ptvc = pkt.PTVCReply()
1389 if not ptvc.Null() and not ptvc.Empty():
1390 ptvc_reply = ptvc.Name()
1394 errors = pkt.CompletionCodes()
1395 print '\t\t%s, NULL, %s, NULL,' % (ptvc_request, ptvc_reply)
1396 print '\t\t%s },\n' % (errors.Name())
1398 print '\t{ 0, 0, 0, NULL }'
1401 print "/* ncp funcs that require a subfunc */"
1402 print "static const guint8 ncp_func_requires_subfunc[] = {"
1404 for pkt in packets.Members():
1405 if pkt.HasSubFunction():
1406 hi_func = pkt.FunctionCode('high')
1407 if not hi_seen.has_key(hi_func):
1408 print "\t0x%02x," % (hi_func)
1409 hi_seen[hi_func] = 1
1414 print '#include "ncp2222.h"'