In this project you will implement a pseudo character device driver for group communication. Each message will be delivered to subscribers only and subscription management and blocking can be possible. The devices can only start working through a simple authentication process. We will call this device as ktwit.
When the device is opened, reading and writing is not possible. The opening process should issue a ioctl(fd,KTWAUTH, ...) request to authenticate an id, which is an unsigned char value. In order to authenticate, a correct passid, a short integer should be given. After authentication, all writes to device will be sent to queues of the subscriber ids. An id can subscribe to more than one ids including itself. When device is read, the first message from a subscribed id is read.
In order to subscribe an id, an authenticated id sends a ioctl(fd, KTWSUB,id) request. In order to unsbuscribe, ioctl(fd, KTWUNS,id) request is sent. All of the messages coming from an id before subscription are lost. In other words, when an id writes a message, the message is delivered to current subscribers only. The message is not accessible for the others.
The authentication information is a map of unsigned char to short values, the id and the passid. When the device module is first loaded, this map is empty and there exists no id in the system. An unauthenticated process can issue a ioctl(fd,KTWNEW, ...) request to create a new id. If id is in use the request fails, otherwise the id is created with given passid and process is authenticated. An authenticated process can issue the same request to change its passid if the authenticated id matches the request. The authentication information is global to the device driver (or module), all minor devices use the same authentication map.
On the other hand the messaging is specific per minor device. An id can have different subscribers for different minor devices. Also the written messages are delivered to only authenticated subscribers of the same minor devices. A process has to authenticate for each minor device it wants to read. In other words each minor device is an instance of a different messaging system where authentication information is shared.
The module has the following parameters that can be set at module load time: ioctl() calls:
If ktw_major is not specified, the system will automatically determine a major number. If it is specified, the provided number will be used. On module load, ktw_minor minor devices are created. Default is 4. ktw_maxsize is used to limit the size of each message written on the device. If a longer write() call is issued, the message is truncated to this size. Default is 256.
You need a group of ioctl() commands to configure each queue, They are defined within the ktwit.h as follows:
These calls are explained as:
This operation is used to authenticate to an id. The parameter of ioctl() is the id and
passid information by macro KTW_MKAUTH. For example:
ioctl(fd, KTW_IOCTAUTH, KTW_MKAUTH(’A’,12345)) will authenticate the id ’A’ with
passid 12345.
If the given pair is in the authentication map, it succeeds (ioctl returns 0), otherwise -1 is returned and error no is set to EINVAL.
Similar to KTW_IOCTAUTH but creates the id and authenticates the process.
ioctl(fd, KTW_IOCTNEW, KTW_MKAUTH(’A’,12345))
If process is not authenticated yet, it tries to insert the id,passid pair into authentication map. If id exists in the map, it returns -1 and error no is set to EINVAL. Otherwise the id,passid pair is inserted and authentication succeeds.
If process is already authenticated and the authentication id is same with the id in the parameter, the given passid is updated on the authentication map (it works like password change). If ids are different it fails and error number is set to EINVAL.
All ioctl requests but KTW_IOCTNEW fails with error number EBADF if the process is not authenticated yet.
It is used to subscribe an id.
ioctl(fd, KTW_IOCTSUB, ’A’)
After this call the currently authenticated id will get messages sent by id ’A’.
Note that the subscription information is persistent across multiple open/close sessions on the same minor device. It is kept per minor device until the module is unloaded.
If the id is already subscribed, it is silently ignored and operation succeeds.
It is used to unsubscribe an id.
ioctl(fd, KTW_IOCTUNSUB, ’A’)
After this call the currently authenticated id will not get further messages sent by id ’A’.
If the id is not subscribed, it is silently ignored and operation succeeds.
It is used to clear currently unread messages by the current id. ioctl(fd, KTW_IOCCLR)
After this call, all messages waiting to be read by the current id are deleted from the
queue.
It is used for id to stop another id from getting messages.
ioctl(fd, KTW_IOCTBLOCK, ’A’)
After this call, the subscription of id ’A’ to current id is broken and further subscription
requests from ’A’ fails. There is no way of unblocking a blocked id.
It is used for getting a list of subscribed ids of current id. struct ktw_set sset
ioctl(fd, KTW_IOCGSUBS, & sset )
call will put the list of all subscribed ids into sset structure.
It is used for getting a list of subscriber ids of current id. struct ktw_set sset
ioctl(fd, KTW_IOCGFOLL, & sset )
call will put the list of all followers into sset structure.
Implement this device driver with open, read, write, close, ioctl , and poll functions in Linux. You
can use the scull sample device driver code given in the sources section of the home
page:
http://www.ceng.metu.edu.tr/courses/ceng536/sources/ldd3-samples-1.0.1
Also you need to use the guidelines in the online book:
http://www.ceng.metu.edu.tr/courses/ceng536/documents/ldd3_pdf/
Please look at Qemu utility in all linux distributions. It is a processor simulator that can boot the kernel of your machine. It will help building and testing without crashing a working system.