1 diff -Naur linux-2.6.25.4/Documentation/networking/ipn.txt linux-2.6.25.4-ipn/Documentation/networking/ipn.txt
2 --- linux-2.6.25.4/Documentation/networking/ipn.txt 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.25.4-ipn/Documentation/networking/ipn.txt 2008-05-31 15:27:49.000000000 +0200
5 +Inter Process Networking (IPN)
7 +IPN is an Inter Process Communication service. It uses the same programming
8 +interface and protocols used for networking. Processes using IPN are connected
9 +to a "network" (many to many communication). The messages or packets sent by a
10 +process on an IPN network can be delivered to many other processes connected to
11 +the same IPN network, potentially to all the other processes. Different
12 +protocols can be defined on the IPN service. The basic one is the broadcast
13 +(level 1) protocol: all the packets get received by all the processes but the
14 +sender. It is also possible to define more sophisticated protocols. For example
15 +it is possible to have IPN sockets dipatching packets using the Ethernet
16 +protocol (like a Virtual Distributed Ethernet - VDE switch), or Internet
17 +Protocol (like a layer 3 switch). These are just examples, several other
18 +policies can be defined.
23 +The Berkeley socket Application Programming Interface (API) was designed for
24 +client server applications and for point-to-point communications. There is not
25 +a support for broadcasting/multicasting domains.
27 +IPN updates the interface by introducing a new protocol family (PF_IPN or
28 +AF_IPN). PF_IPN is similar to PF_UNIX but for IPN the Socket API calls have a
29 +different (extended) behavior.
31 + #include <sys/socket.h>
33 + #include <sys/ipn.h>
35 + sockfd = socket(AF_IPN, int socket_type, int protocol);
37 +creates a communication socket. The only socket_type defined is SOCK_RAW, other
38 +socket_types can be used for future extensions. A socket cannot be used to send
39 +or receive data until it gets connected (using the "connect" call). The
40 +protocol argument defines the policy used by the socket. Protocol IPN_BROADCAST
41 +(1) is the basic policy: a packet is sent to all the receipients but the sender
42 +itself. The policy IPN_ANY (0) can be used to connect or bind a pre-existing
43 +IPN network regardless of the policy used. (2 will be IPN_VDESWITCH and 3
46 +The address format is the same of PF_UNIX (a.k.a PF_LOCAL), see unix(7) manual.
48 + int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
50 +This call creates an IPN network if it does not exist, or join an existing
51 +network (just for management) if it already exists. The policy of the network
52 +must be consistent with the protocol argument of the "socket" call. A new
53 +network has the policy defined for the socket. "bind" or "connect" operations
54 +on existing networks fail if the policy of the socket is neither IPN_ANY nor
55 +the same of the network. (A network should not be created by a IPN_ANY socket).
56 +An IPN network appears in the file system as a unix socket. The execution
57 +permission (x) on this file is required for "bind' to succeed (otherwise -EPERM
58 +is returned). Similarly the read/write permissions (rw) permits the "connect"
59 +operation for reading (receiving) or writing (sending) packets respectively.
60 +When a socket is bound (but not connected) to a IPN network the process does
61 +not receive or send any data but it can call "ioctl" or "setsockopt" to
62 +configure the network.
64 + int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
66 +This call connects a socket to an existing IPN network. The socket can be
67 +already bound (through the "bind" call) or unbound. Unbound connected sockets
68 +receive and send data but they cannot configure the network. The read or write
69 +permission on the socket (rw) is required to "connect" the channel and
70 +read/write respectively. When "connect" succeeds and provided the socket has
71 +appropriate permissions, the process can sends packets and receives all the
72 +packets sent by other processes and delivered to it by the network policy. The
73 +socket can receive data at any time (like a network interface) so the process
74 +must be able to handle incoming data (using select/poll or multithreading).
75 +Obviously higher lever protocols can also prevent the reception of unexpected
76 +messages by design. It is the case of networks used with with exactly one
77 +sender, all the other processes can simply receive the data and the sender will
78 +never receive any packet. It is also possible to have sockets with different
79 +roles assigning reading permission to some and writing permissions to others.
80 +If data overrun occurs there can be data loss or the sender can be blocked
81 +depending on the policy of the socket (LOSSY or LOSSLESS, see over). Bind must
82 +be called before connect. The correct sequences are: socket+bind: just for
83 +management, socket+bind+connect: management and communication. socket+connect:
84 +communication without management).
86 +The calls "accept" and "listen" are not defined for AF_IPN, as there is not any
87 +server. All the communication takes place among peers.
89 +Data can be sent and received using read, write, send, recv, sendto, recvfrom, sendmsg, recvmsg.
91 +Socket options and flags.
92 +-------------------------
94 +These options can be set by getsockopt and setsockopt.
96 +There are two different kinds of options: network options and node options. The
97 +formers define the structure of the network and must be set prior to bind. It
98 +is not currently possible to change this flag of an existing network. When a
99 +socket is bound and/or connected to an existing network getsockopt gives the
100 +current value of the options. Node options define parameters of the node. These
101 +must be set prior to connect.
105 +IPN_SO_FLAGS: This tag permits to set/get the network flags.
107 +IPN_FLAG_LOSSLESS: this flag defines the behavior in case of network
108 +overloading or data overrun, i.e. when some process are too slow in consuming
109 +the packets for the network buffers. When the network is LOSSY (the flag is
110 +cleared) packets get dropped in case of buffer overflow. A LOSSLESS (flag set)
111 +IPN network blocks the sender if the buffer is full. LOSSY is the default
114 +IPN_SO_NUMNODES: max number of connected sockets (default value 32)
116 +IPN_SO_MTU: maximum transfer unit: maximum size of packets (default value 1514,
117 +Ethernet frame, including VLAN).
119 +IPN_SO_MSGPOOLSIZE: size of the buffer (#of pending packets, default value 8).
120 +This option has two different meanings depending on the LOSSY/LOSSLESS behavior
121 +of the network. For LOSSY networks, this is the maximum number of pending
122 +packets of each node. For LOSSLESS network this is the global number of the
123 +pending packets in the network. When the same packet is sent to many
124 +destinations it is counted just once.
126 +IPN_SO_MODE: this option specifies the permission to use when the socket gets
127 +created on the file system. It is modified by the process' umask in the usual
128 +way. The created socket permission are (mode & ~umask).
132 +IPN_SO_PORT: (default value IPN_PORTNO_ANY) This option specify the port number
133 +where the socket must be connected. When IPN_PORTNO_ANY the port number is
134 +decided by the service. There can be network services where different ports
135 +have different definitions (e.g. different VLANs for ports of virtual Ethernet
138 +IPN_SO_DESCR: This is the description of the node. It is a string, having
139 +maxlength IPN_DESCRLEN. It is just used by debugging tools.
141 +TAP and GRAB nodes for IPN networks
143 +It is possible to connect IPN sockets to virtual and real network interfaces
144 +using specific ioctl and provided the user has the permission to configure the
145 +network (e.g. the CAP_NET_ADMIN Posix capability). A virtual interface
146 +connected to an IPN network is similar to a tap interface (provided by the
147 +tuntap module). A tap interface appears as an ethernet interface to the hosting
148 +operating system, all the packets sent and received through the tap interface
149 +get received and sent by the application which created the tap interface. IPN
150 +virtual network interface appears in the same way but the packets are received
151 +and sent through the IPN network and delivered consistently with the policy
152 +(BROADCAST acts as a basic HUB for the connected processes). It is also
153 +possible to *grab* a real interface. In this case the closest example is the
154 +Linux kernel ethernet bridge. When a real interface is connected to a IPN all
155 +the packets received from the real network are injected also into the IPN and
156 +all the packets sent by the IPN through the real network 'port' get sent on the
159 +ioctl is used for creation or control of TAP or GRAB interfaces.
161 + int ioctl(int d, int request, .../* arg */);
163 +A list of the request values currently supported follows.
165 +IPN_CONN_NETDEV: (struct ifreq *arg). This call creates a TAP interface or
166 +implements a GRAB on an existing interface and connects it to a bound IPN
167 +socket. The field ifr_flags can be IPN_NODEFLAG_TAP for a TAP interface,
168 +IPN_NODEFLAG_GRAB to grab an existing interface. The field ifr_name is the
169 +desired name for the new TAP interface or is the name of the interface to grab
170 +(e.g. eth0). For TAP interfaces, ifr_name can be an empty string. The interface
171 +in this latter case is named ipn followed by a number (e.g. ipn0, ipn1, ...).
172 +This ioctl must be used on a bound but unconnected socket. When the call
173 +succeeds, the socket gets the connected status, but the packets are sent and
174 +received through the interface. Persistence apply only to interface nodes (TAP
177 +IPN_SETPERSIST (int arg). If (arg != 0) it gives the interface the persistent
178 +status: the network interface survives and stay connected to the IPN network
179 +when the socket is closed. When (arg == 0) the standard behavior is resumed:
180 +the interface is deleted or the grabbing is terminated when the socket is
183 +IPN_JOIN_NETDEV: (struct ifreq *arg). This call reconnects a socket to an
184 +existing persistent node. The interface can be defined either by name
185 +(ifr_name) or by index (ifr_index). If there is already a socket controlling
186 +the interface this call fails (EADDRNOTAVAIL).
188 +There are also some ioctl that can be used by a sysadm to give/clear
189 +persistence on existing IPN interfaces. These calls apply to unbound sockets.
191 +IPN_SETPERSIST_NETDEV: (struct ifreq *arg). This call sets the persistence
192 +status of an IPN interface. The interface can be defined either by name
193 +(ifr_name) or by index (ifr_index).
195 +IPN_CLRPERSIST_NETDEV: (struct ifreq *arg). This call clears the persistence
196 +status of an IPN interface. The interface is specified as in the opposite call
197 +above. The interface is deleted (TAP) or the grabbing is terminated when the
198 +socket is closed, or immediately if the interface is not controlled by a
199 +socket. If the IPN network had the interface as its sole node, the IPN network
202 +When unloading the ipn kernel module, all the persistent flags of interfaces
208 +IPN is able to give a unifying solution to several problems and creates new
209 +opportunities for applications.
211 +Several existing tools can be implemented using IPN sockets:
213 + * VDE. Level 2 service implements a VDE switch in the kernel, providing a
214 + considerable speedup.
215 + * Tap (tuntap) networking for virtual machines
216 + * Kernel ethernet bridge
217 + * All the applications which need multicasting of data streams, like tee
219 +A continuous stream of data (like audio/video/midi etc) can be sent on an IPN
220 +network and several application can receive the broadcast just by joining the
223 +It is possible to write programs that forward packets between different IPN
224 +networks running on the same or on different systems extending the IPN in the
225 +same way as cables extend ethernet networks connecting switches or hubs
226 +together. (VDE cables are examples of such a kind of programs).
228 +IPN interface to protocol modules
229 +---------------------------------
231 +struct ipn_protocol {
233 + int (*ipn_p_newport)(struct ipn_node *newport);
234 + int (*ipn_p_handlemsg)(struct ipn_node *from,struct msgpool_item *msgitem, int depth);
235 + void (*ipn_p_delport)(struct ipn_node *oldport);
236 + void (*ipn_p_postnewport)(struct ipn_node *newport);
237 + void (*ipn_p_predelport)(struct ipn_node *oldport);
238 + int (*ipn_p_newnet)(struct ipn_network *newnet);
239 + void (*ipn_p_delnet)(struct ipn_network *oldnet);
240 + int (*ipn_p_setsockopt)(struct ipn_node *port,int optname,
241 + char __user *optval, int optlen);
242 + int (*ipn_p_getsockopt)(struct ipn_node *port,int optname,
243 + char __user *optval, int *optlen);
244 + int (*ipn_p_ioctl)(struct ipn_node *port,unsigned int request,
245 + unsigned long arg);
248 +int ipn_proto_register(int protocol,struct ipn_protocol *ipn_service);
249 +int ipn_proto_deregister(int protocol);
251 +void ipn_proto_sendmsg(struct ipn_node *to, struct msgpool_item *msg, int depth);
254 +A protocol (sub) module must define its own ipn_protocol structure (maybe a
255 +global static variable).
257 +ipn_proto_register must be called in the module init to register the protocol
258 +to the IPN core module. ipn_proto_deregister must be called in the destructor
259 +of the module. It fails if there are already running networks based on this
262 +Only two fields must be initialized in any case: ipn_p_newport and
265 +ipn_p_newport is the new network node notification. The return value is the
266 +port number of the new node. This call can be used to allocate and set private
267 +data used by the protocol (the field proto_private of the struct ipn_node has
268 +been defined for this purpose).
270 +ipn_p_handlemsg is the notification of a message that must be dispatched. This
271 +function should call ipn_proto_sendmsg for each recipient. It is possible for
272 +the protocol to change the message (provided the global length of the packet
273 +does not exceed the MTU of the network). Depth is for loop control. Two IPN can
274 +be interconnected by kernel cables (not implemented yet). Cycles of cables
275 +would generate infinite loops of packets. After a pre-defined number of hops
276 +the packet gets dropped (it is like EMLINK for symbolic links). Depth value
277 +must be copied to all ipn_proto_sendmsg calls. Usually the handlemsg function
278 +has the following structure:
280 +static int ipn_xxxxx_handlemsg(struct ipn_node *from, struct msgpool_item *msgitem, int depth)
282 + /* compute the set of receipients */
283 + for (/*each receipient "to"*/)
284 + ipn_proto_sendmsg(to,msgitem,depth);
287 +It is also possible to send different packets to different recipients.
289 +struct msgpool_item *newitem=ipn_msgpool_alloc(from->ipn);
290 +/* create a new contents for the packet by filling in newitem->len and newitem->data */
291 +ipn_proto_sendmsg(recipient1,newitem,depth);
292 +ipn_proto_sendmsg(recipient2,newitem,depth);
294 +ipn_msgpool_put(newitem);
296 +(please remember to call ipn_msgpool_put after the sendmsg of packets allocated
297 +by the protocol submodule).
299 +ipn_p_delport is used to deallocate port related data structures.
301 +ipn_p_postnewport and ipn_p_predelport are used to notify new nodes or deleted
302 +nodes. newport and delport get called before activating the port and after
303 +disactivating it respectively, therefore it is not possible to use the new port
304 +or deleted port to signal the change on the net itself. ipn_p_postnewport and
305 +ipn_p_predelport get called just after the activation and just before the
306 +deactivation thus the protocols can already send packets on the network.
308 +ipn_p_newnet and ipn_p_delnet notify the creation/deletion of a IPN network
309 +using the given protocol.
311 +ipn_p_setsockopt and ipn_p_getsockopt can be used to provide specific socket
314 +ipn_p_ioctl protocols can implement also specific ioctl services.
315 diff -Naur linux-2.6.25.4/MAINTAINERS linux-2.6.25.4-ipn/MAINTAINERS
316 --- linux-2.6.25.4/MAINTAINERS 2008-05-15 17:00:12.000000000 +0200
317 +++ linux-2.6.25.4-ipn/MAINTAINERS 2008-05-31 15:27:49.000000000 +0200
318 @@ -2160,6 +2160,15 @@
319 W: http://openipmi.sourceforge.net/
322 +IPN INTER PROCESS NETWORKING
324 +M: renzo@cs.unibo.it
325 +P: Ludovico Gardenghi
326 +M: garden@cs.unibo.it
327 +L: netdev@vger.kernel.org
328 +W: http://wiki.virtualsquare.org
332 P: Arnaldo Carvalho de Melo
333 M: acme@ghostprotocols.net
334 diff -Naur linux-2.6.25.4/include/linux/net.h linux-2.6.25.4-ipn/include/linux/net.h
335 --- linux-2.6.25.4/include/linux/net.h 2008-05-15 17:00:12.000000000 +0200
336 +++ linux-2.6.25.4-ipn/include/linux/net.h 2008-05-31 15:27:51.000000000 +0200
341 -#define NPROTO 34 /* should be enough for now.. */
342 +#define NPROTO 35 /* should be enough for now.. */
344 #define SYS_SOCKET 1 /* sys_socket(2) */
345 #define SYS_BIND 2 /* sys_bind(2) */
346 diff -Naur linux-2.6.25.4/include/linux/netdevice.h linux-2.6.25.4-ipn/include/linux/netdevice.h
347 --- linux-2.6.25.4/include/linux/netdevice.h 2008-05-15 17:00:12.000000000 +0200
348 +++ linux-2.6.25.4-ipn/include/linux/netdevice.h 2008-05-31 15:27:51.000000000 +0200
350 struct net_bridge_port *br_port;
352 struct macvlan_port *macvlan_port;
354 + struct ipn_node *ipn_port;
356 /* class/net/name entry */
358 diff -Naur linux-2.6.25.4/include/linux/socket.h linux-2.6.25.4-ipn/include/linux/socket.h
359 --- linux-2.6.25.4/include/linux/socket.h 2008-05-15 17:00:12.000000000 +0200
360 +++ linux-2.6.25.4-ipn/include/linux/socket.h 2008-05-31 15:27:51.000000000 +0200
362 #define AF_BLUETOOTH 31 /* Bluetooth sockets */
363 #define AF_IUCV 32 /* IUCV sockets */
364 #define AF_RXRPC 33 /* RxRPC sockets */
365 -#define AF_MAX 34 /* For now.. */
366 +#define AF_IPN 34 /* IPN sockets */
367 +#define AF_MAX 35 /* For now.. */
369 /* Protocol families, same as address families. */
370 #define PF_UNSPEC AF_UNSPEC
372 #define PF_BLUETOOTH AF_BLUETOOTH
373 #define PF_IUCV AF_IUCV
374 #define PF_RXRPC AF_RXRPC
375 +#define PF_IPN AF_IPN
376 #define PF_MAX AF_MAX
378 /* Maximum queue length specifiable by listen. */
379 diff -Naur linux-2.6.25.4/include/net/af_ipn.h linux-2.6.25.4-ipn/include/net/af_ipn.h
380 --- linux-2.6.25.4/include/net/af_ipn.h 1970-01-01 01:00:00.000000000 +0100
381 +++ linux-2.6.25.4-ipn/include/net/af_ipn.h 2008-05-31 15:27:51.000000000 +0200
383 +#ifndef __LINUX_NET_AFIPN_H
384 +#define __LINUX_NET_AFIPN_H
387 +#define IPN_BROADCAST 1
389 +#define IPN_VDESWITCH 2
390 +#define IPN_VDESWITCH_L3 3
392 +#define IPN_SO_PREBIND 0x80
393 +#define IPN_SO_PORT 0
394 +#define IPN_SO_DESCR 1
395 +#define IPN_SO_CHANGE_NUMNODES 2
396 +#define IPN_SO_HANDLE_OOB 3
397 +#define IPN_SO_WANT_OOB_NUMNODES 4
398 +#define IPN_SO_MTU (IPN_SO_PREBIND | 0)
399 +#define IPN_SO_NUMNODES (IPN_SO_PREBIND | 1)
400 +#define IPN_SO_MSGPOOLSIZE (IPN_SO_PREBIND | 2)
401 +#define IPN_SO_FLAGS (IPN_SO_PREBIND | 3)
402 +#define IPN_SO_MODE (IPN_SO_PREBIND | 4)
404 +#define IPN_PORTNO_ANY -1
406 +#define IPN_DESCRLEN 128
408 +#define IPN_FLAG_LOSSLESS 1
409 +#define IPN_FLAG_EXCL 2
410 +#define IPN_FLAG_TERMINATED 0x1000
413 +#define IPN_CHECK _IOW('I', 199, int)
414 +#define IPN_SETPERSIST_NETDEV _IOW('I', 200, int)
415 +#define IPN_CLRPERSIST_NETDEV _IOW('I', 201, int)
416 +#define IPN_CONN_NETDEV _IOW('I', 202, int)
417 +#define IPN_JOIN_NETDEV _IOW('I', 203, int)
418 +#define IPN_SETPERSIST _IOW('I', 204, int)
420 +#define IPN_OOB_NUMNODE_TAG 0
422 +/* OOB message for change of numnodes
423 + * Common fields for oob IPN signaling:
424 + * @level=level of the service who generated the oob
425 + * @tag=tag of the message
427 + * @numreaders=number of readers
428 + * @numwriters=number of writers
430 +struct numnode_oob {
438 +#include <linux/socket.h>
439 +#include <linux/mutex.h>
440 +#include <linux/un.h>
441 +#include <net/sock.h>
442 +#include <linux/netdevice.h>
444 +#define IPN_HASH_SIZE 256
446 +/* The AF_IPN socket */
447 +struct msgpool_item;
449 +struct pre_bind_parms;
454 + * @nodelist=pointers for connectqueue or unconnectqueue (see network)
455 + * @protocol=kind of service 0->standard broadcast
456 + * @flags= see IPN_NODEFLAG_xxx
457 + * @shutdown= SEND_SHUTDOWN/RCV_SHUTDOWN and OOBRCV_SHUTDOWN
458 + * @descr=description of this port
459 + * @portno=when connected: port of the netowrk (<0 means unconnected)
460 + * @msglock=mutex on the msg queue
461 + * @totmsgcount=total # of pending msgs
462 + * @oobmsgcount=# of pending oob msgs
463 + * @msgqueue=queue of messages
464 + * @oobmsgqueue=queue of messages
465 + * @read_wait=waitqueue for reading
466 + * @net=current network
467 + * @dev=device (TAP or GRAB)
468 + * @ipn=network we are connected to
469 + * @pbp=temporary storage for parms that must be set prior to bind
470 + * @proto_private=handle for protocol private data
473 + struct list_head nodelist;
475 + volatile unsigned char flags;
476 + unsigned char shutdown;
477 + char descr[IPN_DESCRLEN];
479 + spinlock_t msglock;
480 + unsigned short totmsgcount;
481 + unsigned short oobmsgcount;
482 + struct list_head msgqueue;
483 + struct list_head oobmsgqueue;
484 + wait_queue_head_t read_wait;
486 + struct net_device *dev;
487 + struct ipn_network *ipn;
488 + struct pre_bind_parms *pbp;
489 + void *proto_private;
492 +#define IPN_NODEFLAG_BOUND 0x1 /* bind succeeded */
493 +#define IPN_NODEFLAG_INUSE 0x2 /* is currently "used" (0 for persistent, unbound interfaces) */
494 +#define IPN_NODEFLAG_PERSIST 0x4 /* if persist does not disappear on close (net interfaces) */
495 +#define IPN_NODEFLAG_TAP 0x10 /* This is a tap interface */
496 +#define IPN_NODEFLAG_GRAB 0x20 /* This is a grab of a real interface */
497 +#define IPN_NODEFLAG_DEVMASK 0x30 /* True if this is a device */
498 +#define IPN_NODEFLAG_OOB_NUMNODES 0x40 /* Node wants OOB for NNODES */
503 + * unfortunately we must use a struct sock (most of the fields are useless) as
504 + * this is the standard "agnostic" structure for socket implementation.
505 + * This proofs that it is not "agnostic" enough!
510 + struct ipn_node *node;
514 + * ipn_network network descriptor
516 + * @hnode=hash to find this entry (looking for i-node)
517 + * @unconnectqueue=queue of unconnected (bound) nodes
518 + * @connectqueue=queue of connected nodes (faster for broadcasting)
519 + * @refcnt=reference count (bound or connected sockets)
520 + * @dentry/@mnt=to keep the file system descriptor into memory
521 + * @ipnn_lock=lock for protocol functions
522 + * @protocol=kind of service
523 + * @flags=flags (IPN_FLAG_LOSSLESS)
524 + * @maxports=number of ports available in this network
525 + * @msgpool_nelem=number of pending messages
526 + * @msgpool_size=max number of pending messages *per net* when IPN_FLAG_LOSSLESS
527 + * @msgpool_size=max number of pending messages *per port*when LOSSY
529 + * @send_wait=wait queue waiting for a message in the msgpool (IPN_FLAG_LOSSLESS)
530 + * @msgpool_cache=slab for msgpool (unused yet)
531 + * @proto_private=handle for protocol private data
532 + * @connports=array of connected sockets
534 +struct ipn_network {
535 + struct hlist_node hnode;
536 + struct list_head unconnectqueue;
537 + struct list_head connectqueue;
539 + struct dentry *dentry;
540 + struct vfsmount *mnt;
541 + struct semaphore ipnn_mutex;
543 + struct sockaddr_un sunaddr;
544 + unsigned int protocol;
545 + unsigned int flags;
548 + atomic_t msgpool_nelem;
549 + unsigned short maxports;
550 + unsigned short msgpool_size;
551 + unsigned short mtu;
552 + wait_queue_head_t send_wait;
553 + struct kmem_cache *msgpool_cache;
554 + void *proto_private;
555 + struct ipn_node **connport;
558 +/* struct msgpool_item
559 + * the local copy of the message for dispatching
564 +struct msgpool_item {
567 + unsigned char data[0];
570 +struct msgpool_item *ipn_msgpool_alloc(struct ipn_network *ipnn,int leaky);
571 +void ipn_msgpool_put(struct msgpool_item *old, struct ipn_network *ipnn);
574 + * protocol service:
576 + * @refcnt: number of networks using this protocol
577 + * @newport=upcall for reporting a new port. returns the portno, -1=error
578 + * @handlemsg=dispatch a message.
579 + * should call ipn_proto_sendmsg for each desctination
580 + * can allocate other msgitems using ipn_msgpool_alloc to send
581 + * different messages to different destinations;
582 + * @delport=(may be null) reports the terminatio of a port
583 + * @postnewport,@predelport: similar to newport/delport but during these calls
584 + * the node is (still) connected. Useful when protocols need
585 + * welcome and goodbye messages.
586 + * @ipn_p_setsockopt
587 + * @ipn_p_getsockopt
588 + * @ipn_p_ioctl=(may be null) upcall to manage specific options or ctls.
590 +struct ipn_protocol {
592 + int (*ipn_p_newport)(struct ipn_node *newport);
593 + int (*ipn_p_handlemsg)(struct ipn_node *from,struct msgpool_item *msgitem);
594 + void (*ipn_p_delport)(struct ipn_node *oldport);
595 + void (*ipn_p_postnewport)(struct ipn_node *newport);
596 + void (*ipn_p_predelport)(struct ipn_node *oldport);
597 + int (*ipn_p_newnet)(struct ipn_network *newnet);
598 + int (*ipn_p_resizenet)(struct ipn_network *net,int oldsize,int newsize);
599 + void (*ipn_p_delnet)(struct ipn_network *oldnet);
600 + int (*ipn_p_setsockopt)(struct ipn_node *port,int optname,
601 + char __user *optval, int optlen);
602 + int (*ipn_p_getsockopt)(struct ipn_node *port,int optname,
603 + char __user *optval, int *optlen);
604 + int (*ipn_p_ioctl)(struct ipn_node *port,unsigned int request,
605 + unsigned long arg);
608 +int ipn_proto_register(int protocol,struct ipn_protocol *ipn_service);
609 +int ipn_proto_deregister(int protocol);
611 +int ipn_proto_injectmsg(struct ipn_node *from, struct msgpool_item *msg);
612 +void ipn_proto_sendmsg(struct ipn_node *to, struct msgpool_item *msg);
613 +void ipn_proto_oobsendmsg(struct ipn_node *to, struct msgpool_item *msg);
615 +extern struct sk_buff *(*ipn_handle_frame_hook)(struct ipn_node *p,
616 + struct sk_buff *skb);
619 diff -Naur linux-2.6.25.4/net/Kconfig linux-2.6.25.4-ipn/net/Kconfig
620 --- linux-2.6.25.4/net/Kconfig 2008-05-15 17:00:12.000000000 +0200
621 +++ linux-2.6.25.4-ipn/net/Kconfig 2008-05-31 15:27:52.000000000 +0200
624 source "net/packet/Kconfig"
625 source "net/unix/Kconfig"
626 +source "net/ipn/Kconfig"
627 source "net/xfrm/Kconfig"
628 source "net/iucv/Kconfig"
630 diff -Naur linux-2.6.25.4/net/Makefile linux-2.6.25.4-ipn/net/Makefile
631 --- linux-2.6.25.4/net/Makefile 2008-05-15 17:00:12.000000000 +0200
632 +++ linux-2.6.25.4-ipn/net/Makefile 2008-05-31 15:27:52.000000000 +0200
634 obj-$(CONFIG_INET) += ipv4/
635 obj-$(CONFIG_XFRM) += xfrm/
636 obj-$(CONFIG_UNIX) += unix/
637 +obj-$(CONFIG_IPN) += ipn/
638 ifneq ($(CONFIG_IPV6),)
641 diff -Naur linux-2.6.25.4/net/core/dev.c linux-2.6.25.4-ipn/net/core/dev.c
642 --- linux-2.6.25.4/net/core/dev.c 2008-05-15 17:00:12.000000000 +0200
643 +++ linux-2.6.25.4-ipn/net/core/dev.c 2008-05-31 15:27:52.000000000 +0200
644 @@ -1929,7 +1929,7 @@
646 struct net_device *orig_dev)
648 - if (skb->dev->macvlan_port == NULL)
649 + if (!skb || skb->dev->macvlan_port == NULL)
653 @@ -1942,6 +1942,32 @@
654 #define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb)
657 +#if defined(CONFIG_IPN) || defined(CONFIG_IPN_MODULE)
658 +struct sk_buff *(*ipn_handle_frame_hook)(struct ipn_node *port,
659 + struct sk_buff *skb) __read_mostly;
660 +EXPORT_SYMBOL_GPL(ipn_handle_frame_hook);
662 +static inline struct sk_buff *handle_ipn(struct sk_buff *skb,
663 + struct packet_type **pt_prev,
665 + struct net_device *orig_dev)
667 + struct ipn_node *port;
669 + if (!skb || skb->pkt_type == PACKET_LOOPBACK ||
670 + (port = rcu_dereference(skb->dev->ipn_port)) == NULL)
674 + *ret = deliver_skb(skb, *pt_prev, orig_dev);
677 + return ipn_handle_frame_hook(port, skb);
680 +#define handle_ipn(skb, pt_prev, ret, orig_dev) (skb)
683 #ifdef CONFIG_NET_CLS_ACT
684 /* TODO: Maybe we should just force sch_ingress to be compiled in
685 * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
686 @@ -2074,9 +2100,8 @@
689 skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
692 skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev);
693 + skb = handle_ipn(skb, &pt_prev, &ret, orig_dev);
697 diff -Naur linux-2.6.25.4/net/ipn/Kconfig linux-2.6.25.4-ipn/net/ipn/Kconfig
698 --- linux-2.6.25.4/net/ipn/Kconfig 1970-01-01 01:00:00.000000000 +0100
699 +++ linux-2.6.25.4-ipn/net/ipn/Kconfig 2008-05-31 15:27:52.000000000 +0200
702 +# Unix Domain Sockets
706 + tristate "IPN domain sockets (EXPERIMENTAL)"
707 + depends on EXPERIMENTAL
709 + If you say Y here, you will include support for IPN domain sockets.
710 + Inter Process Networking socket are similar to Unix sockets but
711 + they support peer-to-peer, one-to-many and many-to-many communication
713 + Sub-Modules can be loaded to provide dispatching protocols.
714 + This service include the IPN_BROADCST policy: all the messages get
715 + sent to all the receipients (but the sender itself).
717 + To compile this driver as a module, choose M here: the module will be
720 + If unsure, say 'N'.
722 diff -Naur linux-2.6.25.4/net/ipn/Makefile linux-2.6.25.4-ipn/net/ipn/Makefile
723 --- linux-2.6.25.4/net/ipn/Makefile 1970-01-01 01:00:00.000000000 +0100
724 +++ linux-2.6.25.4-ipn/net/ipn/Makefile 2008-05-31 15:27:52.000000000 +0200
727 +## Makefile for the IPN (Inter Process Networking) domain socket layer.
730 +obj-$(CONFIG_IPN) += ipn.o
732 +ipn-y := af_ipn.o ipn_netdev.o ipn_msgbuf.o
734 diff -Naur linux-2.6.25.4/net/ipn/af_ipn.c linux-2.6.25.4-ipn/net/ipn/af_ipn.c
735 --- linux-2.6.25.4/net/ipn/af_ipn.c 1970-01-01 01:00:00.000000000 +0100
736 +++ linux-2.6.25.4-ipn/net/ipn/af_ipn.c 2008-05-31 15:27:52.000000000 +0200
739 + * Main inter process networking (virtual distributed ethernet) module
740 + * (part of the View-OS project: wiki.virtualsquare.org)
742 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
744 + * This program is free software; you can redistribute it and/or modify
745 + * it under the terms of the GNU General Public License as published by
746 + * the Free Software Foundation; either version 2 of the License, or
747 + * (at your option) any later version.
749 + * Due to this file being licensed under the GPL there is controversy over
750 + * whether this permits you to write a module that #includes this file
751 + * without placing your module under the GPL. Please consult a lawyer for
752 + * advice before doing this.
754 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
758 +#include <linux/init.h>
759 +#include <linux/module.h>
760 +#include <linux/socket.h>
761 +#include <linux/poll.h>
762 +#include <linux/un.h>
763 +#include <linux/list.h>
764 +#include <linux/mount.h>
765 +#include <linux/version.h>
766 +#include <net/sock.h>
767 +#include <net/af_ipn.h>
768 +#include "ipn_netdev.h"
769 +#include "ipn_msgbuf.h"
771 +MODULE_LICENSE("GPL");
772 +MODULE_AUTHOR("VIEW-OS TEAM");
773 +MODULE_DESCRIPTION("IPN Kernel Module");
775 +#define IPN_MAX_PROTO 4
777 +/*extension of RCV_SHUTDOWN defined in include/net/sock.h
778 + * when the bit is set recv fails */
779 +/* NO_OOB: do not send OOB */
780 +#define RCV_SHUTDOWN_NO_OOB 4
781 +/* EXTENDED MASK including OOB */
782 +#define SHUTDOWN_XMASK (SHUTDOWN_MASK | RCV_SHUTDOWN_NO_OOB)
783 +/* if XRCV_SHUTDOWN is all set recv fails */
784 +#define XRCV_SHUTDOWN (RCV_SHUTDOWN | RCV_SHUTDOWN_NO_OOB)
786 +/* Network table and hash */
787 +struct hlist_head ipn_network_table[IPN_HASH_SIZE + 1];
788 +/* not needed. Now protected by ipn_glob_mutex
790 + * DEFINE_SPINLOCK(ipn_table_lock);
792 +static struct kmem_cache *ipn_network_cache;
793 +static struct kmem_cache *ipn_node_cache;
794 +static struct kmem_cache *ipn_msgitem_cache;
795 +static DECLARE_MUTEX(ipn_glob_mutex);
797 +/* Protocol 1: HUB/Broadcast default protocol. Function Prototypes */
798 +static int ipn_bcast_newport(struct ipn_node *newport);
799 +static int ipn_bcast_handlemsg(struct ipn_node *from,
800 + struct msgpool_item *msgitem);
802 +/* default protocol IPN_BROADCAST (0) */
803 +static struct ipn_protocol ipn_bcast = {
805 + .ipn_p_newport=ipn_bcast_newport,
806 + .ipn_p_handlemsg=ipn_bcast_handlemsg};
807 +/* Protocol table */
808 +static struct ipn_protocol *ipn_protocol_table[IPN_MAX_PROTO]={&ipn_bcast};
810 +/* Socket call function prototypes */
811 +static int ipn_release(struct socket *);
812 +static int ipn_bind(struct socket *, struct sockaddr *, int);
813 +static int ipn_connect(struct socket *, struct sockaddr *,
814 + int addr_len, int flags);
815 +static int ipn_getname(struct socket *, struct sockaddr *, int *, int);
816 +static unsigned int ipn_poll(struct file *, struct socket *, poll_table *);
817 +static int ipn_ioctl(struct socket *, unsigned int, unsigned long);
818 +static int ipn_shutdown(struct socket *, int);
819 +static int ipn_sendmsg(struct kiocb *, struct socket *,
820 + struct msghdr *, size_t);
821 +static int ipn_recvmsg(struct kiocb *, struct socket *,
822 + struct msghdr *, size_t, int);
823 +static int ipn_setsockopt(struct socket *sock, int level, int optname,
824 + char __user *optval, int optlen);
825 +static int ipn_getsockopt(struct socket *sock, int level, int optname,
826 + char __user *optval, int __user *optlen);
828 +/* Network table Management
829 + * inode->ipn_network hash table
830 + * LOCKING: MUTEX ipn_glob_mutex must be LOCKED*/
831 +static inline void ipn_insert_network(struct hlist_head *list, struct ipn_network *ipnn)
833 + /* *IPNTL* spin_lock(&ipn_table_lock); */
834 + hlist_add_head(&ipnn->hnode, list);
835 + /* *IPNTL* spin_unlock(&ipn_table_lock); */
838 +static inline void ipn_remove_network(struct ipn_network *ipnn)
840 + /* *IPNTL* spin_lock(&ipn_table_lock); */
841 + hlist_del(&ipnn->hnode);
842 + /* *IPNTL* spin_unlock(&ipn_table_lock); */
845 +static struct ipn_network *ipn_find_network_byinode(struct inode *i)
847 + struct ipn_network *ipnn;
848 + struct hlist_node *node;
850 + /* *IPNTL* spin_lock(&ipn_table_lock);*/
851 + hlist_for_each_entry(ipnn, node,
852 + &ipn_network_table[i->i_ino & (IPN_HASH_SIZE - 1)], hnode) {
853 + struct dentry *dentry = ipnn->dentry;
855 + if(ipnn->refcnt > 0 && dentry && dentry->d_inode == i)
860 + /* *IPNTL* spin_unlock(&ipn_table_lock); */
864 +/* msgpool management
865 + * msgpool_item are ipn_network dependent (each net has its own MTU)
866 + * for each message sent there is one msgpool_item and many struct msgitem
867 + * one for each receipient.
868 + * msgitem are connected to the node's msgqueue or oobmsgqueue.
869 + * when a message is delivered to a process the msgitem is deleted and
870 + * the count of the msgpool_item is decreased.
871 + * msgpool_item elements gets deleted automatically when count is 0*/
874 + struct list_head list;
875 + struct msgpool_item *msg;
878 +/* alloc a fresh msgpool item. count is set to 1.
879 + * the typical use is
880 + * ipn_msgpool_alloc
881 + * for each receipient
882 + * enqueue messages to the process (using msgitem), ipn_msgpool_hold
884 + * The message can be delivered concurrently. init count to 1 guarantees
885 + * that it survives at least until is has been enqueued to all
887 +static struct msgpool_item *_ipn_msgpool_alloc(struct ipn_network *ipnn)
889 + struct msgpool_item *new;
890 + if ((new=kmem_cache_alloc(ipnn->msgpool_cache,GFP_KERNEL)) != NULL) {
891 + atomic_set(&new->count,1);
892 + atomic_inc(&ipnn->msgpool_nelem);
897 +struct msgpool_item *ipn_msgpool_alloc(struct ipn_network *ipnn,int leaky)
899 + if (leaky && (ipnn->flags & IPN_FLAG_LOSSLESS) &&
900 + atomic_read(&ipnn->msgpool_nelem) < ipnn->msgpool_size)
903 + return _ipn_msgpool_alloc(ipnn);
906 +/* If the service il LOSSLESS, this msgpool call waits for an
907 + * available msgpool item */
908 +static struct msgpool_item *ipn_msgpool_alloc_locking(struct ipn_network *ipnn)
910 + if (ipnn->flags & IPN_FLAG_LOSSLESS) {
911 + while (atomic_read(&ipnn->msgpool_nelem) >= ipnn->msgpool_size) {
912 + if (wait_event_interruptible_exclusive(ipnn->send_wait,
913 + atomic_read(&ipnn->msgpool_nelem) < ipnn->msgpool_size))
917 + return _ipn_msgpool_alloc(ipnn);
920 +static inline void ipn_msgpool_hold(struct msgpool_item *msg)
922 + atomic_inc(&msg->count);
925 +/* decrease count and delete msgpool_item if count == 0 */
926 +void ipn_msgpool_put(struct msgpool_item *old,
927 + struct ipn_network *ipnn)
929 + if (atomic_dec_and_test(&old->count)) {
930 + kmem_cache_free(ipnn->msgpool_cache,old);
931 + atomic_dec(&ipnn->msgpool_nelem);
932 + if (ipnn->flags & IPN_FLAG_LOSSLESS) /* this could be done anyway */
933 + wake_up_interruptible(&ipnn->send_wait);
938 +static const struct proto_ops ipn_ops = {
940 + .owner = THIS_MODULE,
941 + .release = ipn_release,
943 + .connect = ipn_connect,
944 + .socketpair = sock_no_socketpair,
945 + .accept = sock_no_accept,
946 + .getname = ipn_getname,
948 + .ioctl = ipn_ioctl,
949 + .listen = sock_no_listen,
950 + .shutdown = ipn_shutdown,
951 + .setsockopt = ipn_setsockopt,
952 + .getsockopt = ipn_getsockopt,
953 + .sendmsg = ipn_sendmsg,
954 + .recvmsg = ipn_recvmsg,
955 + .mmap = sock_no_mmap,
956 + .sendpage = sock_no_sendpage,
959 +static struct proto ipn_proto = {
961 + .owner = THIS_MODULE,
962 + .obj_size = sizeof(struct ipn_sock),
966 + * ipn_node is a separate structure, pointed by ipn_sock -> node
967 + * when a node is "persistent", ipn_node survives while ipn_sock gets released*/
968 +static int ipn_create(struct net *net,struct socket *sock, int protocol)
970 + struct ipn_sock *ipn_sk;
971 + struct ipn_node *ipn_node;
973 + if (net != &init_net)
974 + return -EAFNOSUPPORT;
976 + if (sock->type != SOCK_RAW)
977 + return -EPROTOTYPE;
979 + protocol=protocol-1;
981 + protocol=IPN_BROADCAST-1;
982 + if (protocol < 0 || protocol >= IPN_MAX_PROTO ||
983 + ipn_protocol_table[protocol] == NULL)
984 + return -EPROTONOSUPPORT;
985 + ipn_sk = (struct ipn_sock *) sk_alloc(net, PF_IPN, GFP_KERNEL, &ipn_proto);
989 + ipn_sk->node=ipn_node=kmem_cache_alloc(ipn_node_cache,GFP_KERNEL);
991 + sock_put((struct sock *) ipn_sk);
994 + sock_init_data(sock,(struct sock *) ipn_sk);
995 + sock->state = SS_UNCONNECTED;
996 + sock->ops = &ipn_ops;
997 + sock->sk=(struct sock *)ipn_sk;
998 + INIT_LIST_HEAD(&ipn_node->nodelist);
999 + ipn_node->protocol=protocol;
1000 + ipn_node->flags=IPN_NODEFLAG_INUSE;
1001 + ipn_node->shutdown=RCV_SHUTDOWN_NO_OOB;
1002 + ipn_node->descr[0]=0;
1003 + ipn_node->portno=IPN_PORTNO_ANY;
1004 + ipn_node->net=net;
1005 + ipn_node->dev=NULL;
1006 + ipn_node->proto_private=NULL;
1007 + ipn_node->totmsgcount=0;
1008 + ipn_node->oobmsgcount=0;
1009 + spin_lock_init(&ipn_node->msglock);
1010 + INIT_LIST_HEAD(&ipn_node->msgqueue);
1011 + INIT_LIST_HEAD(&ipn_node->oobmsgqueue);
1012 + ipn_node->ipn=NULL;
1013 + init_waitqueue_head(&ipn_node->read_wait);
1014 + ipn_node->pbp=NULL;
1018 +/* update # of readers and # of writers counters for an ipn network.
1019 + * This function sends oob messages to nodes requesting the service */
1020 +/* LOCKING ipnn_mutex is locked */
1021 +static void ipn_net_update_counters(struct ipn_network *ipnn,
1022 + int chg_readers, int chg_writers) {
1023 + ipnn->numreaders += chg_readers;
1024 + ipnn->numwriters += chg_writers;
1025 + if (ipnn->mtu >= sizeof(struct numnode_oob))
1027 + struct msgpool_item *ipn_msg=_ipn_msgpool_alloc(ipnn);
1029 + struct numnode_oob *oob_msg=(struct numnode_oob *)(ipn_msg->data);
1030 + struct ipn_node *ipn_node;
1031 + ipn_msg->len=sizeof(struct numnode_oob);
1032 + oob_msg->level=IPN_ANY;
1033 + oob_msg->tag=IPN_OOB_NUMNODE_TAG;
1034 + oob_msg->numreaders=ipnn->numreaders;
1035 + oob_msg->numwriters=ipnn->numwriters;
1036 + list_for_each_entry(ipn_node, &ipnn->connectqueue, nodelist) {
1037 + if (ipn_node->flags & IPN_NODEFLAG_OOB_NUMNODES)
1038 + ipn_proto_oobsendmsg(ipn_node,ipn_msg);
1040 + ipn_msgpool_put(ipn_msg,ipnn);
1045 +/* flush pending messages (for close and shutdown RCV) */
1046 +/* LOCKING: ipnn_mutex is locked */
1047 +static void ipn_flush_recvqueue(struct ipn_node *ipn_node)
1049 + struct ipn_network *ipnn=ipn_node->ipn;
1050 + spin_lock(&ipn_node->msglock);
1051 + while (!list_empty(&ipn_node->msgqueue)) {
1052 + struct msgitem *msgitem=
1053 + list_first_entry(&ipn_node->msgqueue, struct msgitem, list);
1054 + list_del(&msgitem->list);
1055 + ipn_node->totmsgcount--;
1056 + ipn_msgpool_put(msgitem->msg,ipnn);
1057 + kmem_cache_free(ipn_msgitem_cache,msgitem);
1059 + spin_unlock(&ipn_node->msglock);
1062 +/* flush pending oob messages (for socket close) */
1063 +/* LOCKING: ipnn_mutex is locked */
1064 +static void ipn_flush_oobrecvqueue(struct ipn_node *ipn_node)
1066 + struct ipn_network *ipnn=ipn_node->ipn;
1067 + spin_lock(&ipn_node->msglock);
1068 + while (!list_empty(&ipn_node->oobmsgqueue)) {
1069 + struct msgitem *msgitem=
1070 + list_first_entry(&ipn_node->oobmsgqueue, struct msgitem, list);
1071 + list_del(&msgitem->list);
1072 + ipn_node->totmsgcount--;
1073 + ipn_node->oobmsgcount--;
1074 + ipn_msgpool_put(msgitem->msg,ipnn);
1075 + kmem_cache_free(ipn_msgitem_cache,msgitem);
1077 + spin_unlock(&ipn_node->msglock);
1080 +/* Terminate node. The node is "logically" terminated. */
1081 +/* LOCKING: ipn_glob_lock must be locked here */
1082 +static int ipn_terminate_node(struct ipn_node *ipn_node)
1084 + struct ipn_network *ipnn=ipn_node->ipn;
1086 + if (down_interruptible(&ipnn->ipnn_mutex))
1087 + return -ERESTARTSYS;
1088 + if (ipn_node->portno >= 0) {
1089 + ipn_protocol_table[ipnn->protocol]->ipn_p_predelport(ipn_node);
1090 + ipnn->connport[ipn_node->portno]=NULL;
1092 + list_del(&ipn_node->nodelist);
1093 + ipn_flush_recvqueue(ipn_node);
1094 + ipn_flush_oobrecvqueue(ipn_node);
1095 + if (ipn_node->portno >= 0)
1096 + ipn_protocol_table[ipnn->protocol]->ipn_p_delport(ipn_node);
1097 + ipn_node->ipn=NULL;
1098 + ipn_net_update_counters(ipnn,
1099 + (ipn_node->shutdown & RCV_SHUTDOWN)?0:-1,
1100 + (ipn_node->shutdown & SEND_SHUTDOWN)?0:-1);
1101 + ipn_node->shutdown = SHUTDOWN_XMASK;
1102 + up(&ipnn->ipnn_mutex);
1103 + if (ipn_node->dev)
1104 + ipn_netdev_close(ipn_node);
1105 + /* No more network elements */
1107 + if (ipnn->refcnt == 0)
1109 + ipn_protocol_table[ipnn->protocol]->ipn_p_delnet(ipnn);
1110 + ipn_remove_network(ipnn);
1111 + ipn_protocol_table[ipnn->protocol]->refcnt--;
1112 + if (ipnn->dentry) {
1113 + dput(ipnn->dentry);
1114 + mntput(ipnn->mnt);
1116 + if (ipnn->msgpool_cache)
1117 + ipn_msgbuf_put(ipnn->msgpool_cache);
1118 + if (ipnn->connport)
1119 + kfree(ipnn->connport);
1120 + kmem_cache_free(ipn_network_cache, ipnn);
1121 + module_put(THIS_MODULE);
1124 + if (ipn_node->pbp) {
1125 + kfree(ipn_node->pbp);
1126 + ipn_node->pbp=NULL;
1131 +/* release of a socket */
1132 +static int ipn_release (struct socket *sock)
1134 + struct ipn_sock *ipn_sk=(struct ipn_sock *)sock->sk;
1135 + struct ipn_node *ipn_node=ipn_sk->node;
1137 + if (down_interruptible(&ipn_glob_mutex))
1138 + return -ERESTARTSYS;
1139 + if (ipn_node->flags & IPN_NODEFLAG_PERSIST) {
1140 + ipn_node->flags &= ~IPN_NODEFLAG_INUSE;
1142 + up(&ipn_glob_mutex);
1144 + rv=ipn_terminate_node(ipn_node);
1145 + up(&ipn_glob_mutex);
1148 + kmem_cache_free(ipn_node_cache,ipn_node);
1152 + sock_put((struct sock *) ipn_sk);
1156 +/* _set persist, change the persistence of a node,
1157 + * when persistence gets cleared and the node is no longer used
1158 + * the node is terminated and freed.
1159 + * ipn_glob_mutex must be locked */
1160 +static int _ipn_setpersist(struct ipn_node *ipn_node, int persist)
1164 + ipn_node->flags |= IPN_NODEFLAG_PERSIST;
1166 + ipn_node->flags &= ~IPN_NODEFLAG_PERSIST;
1167 + if (!(ipn_node->flags & IPN_NODEFLAG_INUSE)) {
1168 + rv=ipn_terminate_node(ipn_node);
1170 + kmem_cache_free(ipn_node_cache,ipn_node);
1177 + * lock ipn_glob_mutex and call __ipn_setpersist above */
1178 +static int ipn_setpersist(struct ipn_node *ipn_node, int persist)
1181 + if (ipn_node->dev == NULL)
1183 + if (down_interruptible(&ipn_glob_mutex))
1184 + return -ERESTARTSYS;
1185 + rv=_ipn_setpersist(ipn_node,persist);
1186 + up(&ipn_glob_mutex);
1190 +/* several network parameters can be set by setsockopt prior to bind */
1191 +/* struct pre_bind_parms is a temporary stucture connected to ipn_node->pbp
1192 + * to keep the parameter values. */
1193 +struct pre_bind_parms {
1194 + unsigned short maxports;
1195 + unsigned short flags;
1196 + unsigned short msgpoolsize;
1197 + unsigned short mtu;
1198 + unsigned short mode;
1201 +/* STD_PARMS: BITS_PER_LONG nodes, no flags, BITS_PER_BYTE pending msgs,
1202 + * Ethernet + VLAN MTU*/
1203 +#define STD_BIND_PARMS {BITS_PER_LONG, 0, BITS_PER_BYTE, 1514, 0x777};
1205 +static int ipn_mkname(struct sockaddr_un * sunaddr, int len)
1207 + if (len <= sizeof(short) || len > sizeof(*sunaddr))
1209 + if (!sunaddr || sunaddr->sun_family != AF_IPN)
1212 + * This may look like an off by one error but it is a bit more
1213 + * subtle. 108 is the longest valid AF_IPN path for a binding.
1214 + * sun_path[108] doesnt as such exist. However in kernel space
1215 + * we are guaranteed that it is a valid memory location in our
1216 + * kernel address buffer.
1218 + ((char *)sunaddr)[len]=0;
1219 + len = strlen(sunaddr->sun_path)+1+sizeof(short);
1224 +static int ipn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
1226 + struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
1227 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1228 + struct nameidata nd;
1229 + struct ipn_network *ipnn;
1230 + struct dentry * dentry = NULL;
1232 + struct pre_bind_parms parms=STD_BIND_PARMS;
1234 + //printk("IPN bind\n");
1236 + if (down_interruptible(&ipn_glob_mutex))
1237 + return -ERESTARTSYS;
1238 + if (sock->state != SS_UNCONNECTED ||
1239 + ipn_node->ipn != NULL) {
1244 + if (ipn_node->protocol >= 0 &&
1245 + (ipn_node->protocol >= IPN_MAX_PROTO ||
1246 + ipn_protocol_table[ipn_node->protocol] == NULL)) {
1247 + err= -EPROTONOSUPPORT;
1251 + addr_len = ipn_mkname(sunaddr, addr_len);
1252 + if (addr_len < 0) {
1257 + /* check if there is already an ipn-network socket with that name */
1258 + err = path_lookup(sunaddr->sun_path, LOOKUP_FOLLOW, &nd);
1259 + if (err) { /* it does not exist, NEW IPN socket! */
1260 + unsigned int mode;
1261 + /* Is it everything okay with the parent? */
1262 + err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd);
1264 + goto out_mknod_parent;
1265 + /* Do I have the permission to create a file? */
1266 + dentry = lookup_create(&nd, 0);
1267 + err = PTR_ERR(dentry);
1268 + if (IS_ERR(dentry))
1269 + goto out_mknod_unlock;
1271 + * All right, let's create it.
1273 + if (ipn_node->pbp)
1274 + mode = ipn_node->pbp->mode;
1276 + mode = SOCK_INODE(sock)->i_mode;
1277 + mode = S_IFSOCK | (mode & ~current->fs->umask);
1278 + err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
1280 + goto out_mknod_dput;
1281 + mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
1282 + dput(nd.path.dentry);
1283 + nd.path.dentry = dentry;
1284 + /* create a new ipn_network item */
1285 + if (ipn_node->pbp)
1286 + parms=*ipn_node->pbp;
1287 + ipnn=kmem_cache_zalloc(ipn_network_cache,GFP_KERNEL);
1290 + goto out_mknod_dput_ipnn;
1292 + ipnn->connport=kzalloc(parms.maxports * sizeof(struct ipn_node *),GFP_KERNEL);
1293 + if (!ipnn->connport) {
1295 + goto out_mknod_dput_ipnn2;
1298 + /* module refcnt is incremented for each network, thus
1299 + * rmmod is forbidden if there are persistent node */
1300 + if (!try_module_get(THIS_MODULE)) {
1302 + goto out_mknod_dput_ipnn2;
1304 + memcpy(&ipnn->sunaddr,sunaddr,addr_len);
1305 + ipnn->mtu=parms.mtu;
1306 + ipnn->msgpool_cache=ipn_msgbuf_get(ipnn->mtu);
1307 + if (!ipnn->msgpool_cache) {
1309 + goto out_mknod_dput_putmodule;
1311 + INIT_LIST_HEAD(&ipnn->unconnectqueue);
1312 + INIT_LIST_HEAD(&ipnn->connectqueue);
1314 + ipnn->dentry=nd.path.dentry;
1315 + ipnn->mnt=nd.path.mnt;
1316 + init_MUTEX(&ipnn->ipnn_mutex);
1317 + ipnn->sunaddr_len=addr_len;
1318 + ipnn->protocol=ipn_node->protocol;
1319 + if (ipnn->protocol < 0) ipnn->protocol = 0;
1320 + ipn_protocol_table[ipnn->protocol]->refcnt++;
1321 + ipnn->flags=parms.flags;
1322 + ipnn->numreaders=0;
1323 + ipnn->numwriters=0;
1324 + ipnn->maxports=parms.maxports;
1325 + atomic_set(&ipnn->msgpool_nelem,0);
1326 + ipnn->msgpool_size=parms.msgpoolsize;
1327 + ipnn->proto_private=NULL;
1328 + init_waitqueue_head(&ipnn->send_wait);
1329 + err=ipn_protocol_table[ipnn->protocol]->ipn_p_newnet(ipnn);
1331 + goto out_mknod_dput_putmodule;
1332 + ipn_insert_network(&ipn_network_table[nd.path.dentry->d_inode->i_ino & (IPN_HASH_SIZE-1)],ipnn);
1334 + /* join an existing network */
1335 + if (parms.flags & IPN_FLAG_EXCL) {
1339 + err = vfs_permission(&nd, MAY_EXEC);
1342 + err = -ECONNREFUSED;
1343 + if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode))
1345 + ipnn=ipn_find_network_byinode(nd.path.dentry->d_inode);
1346 + if (!ipnn || (ipnn->flags & IPN_FLAG_TERMINATED) ||
1347 + (ipnn->flags & IPN_FLAG_EXCL))
1349 + list_add_tail(&ipn_node->nodelist,&ipnn->unconnectqueue);
1352 + if (ipn_node->pbp) {
1353 + kfree(ipn_node->pbp);
1354 + ipn_node->pbp=NULL;
1356 + ipn_node->ipn=ipnn;
1357 + ipn_node->flags |= IPN_NODEFLAG_BOUND;
1358 + up(&ipn_glob_mutex);
1362 + path_put(&nd.path);
1364 + up(&ipn_glob_mutex);
1367 +out_mknod_dput_putmodule:
1368 + module_put(THIS_MODULE);
1369 +out_mknod_dput_ipnn2:
1370 + kfree(ipnn->connport);
1371 +out_mknod_dput_ipnn:
1372 + kmem_cache_free(ipn_network_cache,ipnn);
1376 + mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
1377 + path_put(&nd.path);
1381 + up(&ipn_glob_mutex);
1386 +static int ipn_connect(struct socket *sock, struct sockaddr *addr,
1387 + int addr_len, int flags){
1388 + struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr;
1389 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1390 + struct nameidata nd;
1391 + struct ipn_network *ipnn,*previousipnn;
1395 + /* the socket cannot be connected twice */
1396 + if (sock->state != SS_UNCONNECTED)
1399 + if (down_interruptible(&ipn_glob_mutex))
1400 + return -ERESTARTSYS;
1402 + if ((previousipnn=ipn_node->ipn) == NULL) { /* unbound */
1403 + unsigned char mustshutdown=0;
1404 + err = ipn_mkname(sunaddr, addr_len);
1408 + err = path_lookup(sunaddr->sun_path, LOOKUP_FOLLOW, &nd);
1411 + err = vfs_permission(&nd, MAY_READ);
1413 + if (err == -EACCES || err == -EROFS)
1414 + mustshutdown|=RCV_SHUTDOWN;
1418 + err = vfs_permission(&nd, MAY_WRITE);
1420 + if (err == -EACCES)
1421 + mustshutdown|=SEND_SHUTDOWN;
1425 + mustshutdown |= ipn_node->shutdown;
1426 + /* if the combination of shutdown and permissions leaves
1427 + * no abilities, connect returns EACCES */
1428 + if (mustshutdown == SHUTDOWN_XMASK) {
1433 + ipn_node->shutdown=mustshutdown;
1435 + if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode)) {
1436 + err = -ECONNREFUSED;
1439 + ipnn=ipn_find_network_byinode(nd.path.dentry->d_inode);
1440 + if (!ipnn || (ipnn->flags & IPN_FLAG_TERMINATED)) {
1441 + err = -ECONNREFUSED;
1444 + if (ipn_node->protocol == IPN_ANY)
1445 + ipn_node->protocol=ipnn->protocol;
1446 + else if (ipnn->protocol != ipn_node->protocol) {
1450 + path_put(&nd.path);
1451 + ipn_node->ipn=ipnn;
1453 + ipnn=ipn_node->ipn;
1455 + if (down_interruptible(&ipnn->ipnn_mutex)) {
1459 + portno = ipn_protocol_table[ipnn->protocol]->ipn_p_newport(ipn_node);
1460 + if (portno >= 0 && portno<ipnn->maxports) {
1461 + sock->state = SS_CONNECTED;
1462 + ipn_node->portno=portno;
1463 + ipnn->connport[portno]=ipn_node;
1464 + if (!(ipn_node->flags & IPN_NODEFLAG_BOUND)) {
1466 + list_del(&ipn_node->nodelist);
1468 + list_add_tail(&ipn_node->nodelist,&ipnn->connectqueue);
1469 + ipn_net_update_counters(ipnn,
1470 + (ipn_node->shutdown & RCV_SHUTDOWN)?0:1,
1471 + (ipn_node->shutdown & SEND_SHUTDOWN)?0:1);
1473 + ipn_node->ipn=previousipnn; /* undo changes on ipn_node->ipn */
1474 + err=-EADDRNOTAVAIL;
1476 + up(&ipnn->ipnn_mutex);
1477 + up(&ipn_glob_mutex);
1481 + path_put(&nd.path);
1483 + up(&ipn_glob_mutex);
1487 +static int ipn_getname(struct socket *sock, struct sockaddr *uaddr,
1488 + int *uaddr_len, int peer) {
1489 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1490 + struct ipn_network *ipnn=ipn_node->ipn;
1491 + struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
1494 + if (down_interruptible(&ipn_glob_mutex))
1495 + return -ERESTARTSYS;
1497 + *uaddr_len = ipnn->sunaddr_len;
1498 + memcpy(sunaddr,&ipnn->sunaddr,*uaddr_len);
1501 + up(&ipn_glob_mutex);
1506 +static unsigned int ipn_poll(struct file *file, struct socket *sock,
1507 + poll_table *wait) {
1508 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1509 + struct ipn_network *ipnn=ipn_node->ipn;
1510 + unsigned int mask=0;
1513 + poll_wait(file,&ipn_node->read_wait,wait);
1514 + if (ipnn->flags & IPN_FLAG_LOSSLESS)
1515 + poll_wait(file,&ipnn->send_wait,wait);
1516 + /* POLLIN if recv succeeds,
1517 + * POLL{PRI,RDNORM} if there are {oob,non-oob} messages */
1518 + if (ipn_node->totmsgcount > 0) mask |= POLLIN;
1519 + if (!(list_empty(&ipn_node->msgqueue))) mask |= POLLRDNORM;
1520 + if (!(list_empty(&ipn_node->oobmsgqueue))) mask |= POLLPRI;
1521 + if ((!(ipnn->flags & IPN_FLAG_LOSSLESS)) |
1522 + (atomic_read(&ipnn->msgpool_nelem) < ipnn->msgpool_size))
1523 + mask |= POLLOUT | POLLWRNORM;
1528 +/* connect netdev (from ioctl). connect a bound socket to a
1529 + * network device TAP or GRAB */
1530 +static int ipn_connect_netdev(struct socket *sock,struct ifreq *ifr)
1533 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1534 + struct ipn_network *ipnn=ipn_node->ipn;
1535 + if (!capable(CAP_NET_ADMIN))
1537 + if (sock->state != SS_UNCONNECTED)
1540 + return -ENOTCONN; /* Maybe we need a different error for "NOT BOUND" */
1541 + if (down_interruptible(&ipn_glob_mutex))
1542 + return -ERESTARTSYS;
1543 + if (down_interruptible(&ipnn->ipnn_mutex)) {
1544 + up(&ipn_glob_mutex);
1545 + return -ERESTARTSYS;
1547 + ipn_node->dev=ipn_netdev_alloc(ipn_node->net,ifr->ifr_flags,ifr->ifr_name,&err);
1548 + if (ipn_node->dev) {
1550 + portno = ipn_protocol_table[ipnn->protocol]->ipn_p_newport(ipn_node);
1551 + if (portno >= 0 && portno<ipnn->maxports) {
1552 + sock->state = SS_CONNECTED;
1553 + ipn_node->portno=portno;
1554 + ipn_node->flags |= ifr->ifr_flags & IPN_NODEFLAG_DEVMASK;
1555 + ipnn->connport[portno]=ipn_node;
1556 + err=ipn_netdev_activate(ipn_node);
1558 + sock->state = SS_UNCONNECTED;
1559 + ipn_protocol_table[ipnn->protocol]->ipn_p_delport(ipn_node);
1560 + ipn_node->dev=NULL;
1561 + ipn_node->portno= -1;
1562 + ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
1563 + ipnn->connport[portno]=NULL;
1565 + ipn_protocol_table[ipnn->protocol]->ipn_p_postnewport(ipn_node);
1566 + list_del(&ipn_node->nodelist);
1567 + list_add_tail(&ipn_node->nodelist,&ipnn->connectqueue);
1570 + ipn_netdev_close(ipn_node);
1571 + err=-EADDRNOTAVAIL;
1572 + ipn_node->dev=NULL;
1576 + up(&ipnn->ipnn_mutex);
1577 + up(&ipn_glob_mutex);
1581 +/* join a netdev, a socket gets connected to a persistent node
1582 + * not connected to another socket */
1583 +static int ipn_join_netdev(struct socket *sock,struct ifreq *ifr)
1586 + struct net_device *dev;
1587 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1588 + struct ipn_node *ipn_joined;
1589 + struct ipn_network *ipnn=ipn_node->ipn;
1590 + if (sock->state != SS_UNCONNECTED)
1592 + if (down_interruptible(&ipn_glob_mutex))
1593 + return -ERESTARTSYS;
1594 + if (down_interruptible(&ipnn->ipnn_mutex)) {
1595 + up(&ipn_glob_mutex);
1596 + return -ERESTARTSYS;
1598 + dev=__dev_get_by_name(ipn_node->net,ifr->ifr_name);
1600 + dev=__dev_get_by_index(ipn_node->net,ifr->ifr_ifindex);
1601 + if (dev && (ipn_joined=ipn_netdev2node(dev)) != NULL) { /* the interface does exist */
1603 + for (i=0;i<ipnn->maxports && ipn_joined != ipnn->connport[i] ;i++)
1605 + if (i < ipnn->maxports) { /* found */
1606 + /* ipn_joined is substituted to ipn_node */
1607 + ((struct ipn_sock *)sock->sk)->node=ipn_joined;
1608 + ipn_joined->flags |= IPN_NODEFLAG_INUSE;
1610 + kmem_cache_free(ipn_node_cache,ipn_node);
1614 + err=-EADDRNOTAVAIL;
1615 + up(&ipnn->ipnn_mutex);
1616 + up(&ipn_glob_mutex);
1620 +/* set persistence of a node looking for it by interface name
1621 + * (it is for sysadm, to close network interfaces)*/
1622 +static int ipn_setpersist_netdev(struct ifreq *ifr, int value)
1624 + struct net_device *dev;
1625 + struct ipn_node *ipn_node;
1627 + if (!capable(CAP_NET_ADMIN))
1629 + if (down_interruptible(&ipn_glob_mutex))
1630 + return -ERESTARTSYS;
1631 + dev=__dev_get_by_name(&init_net,ifr->ifr_name);
1633 + dev=__dev_get_by_index(&init_net,ifr->ifr_ifindex);
1634 + if (dev && (ipn_node=ipn_netdev2node(dev)) != NULL)
1635 + _ipn_setpersist(ipn_node,value);
1637 + err=-EADDRNOTAVAIL;
1638 + up(&ipn_glob_mutex);
1643 +static int ipn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) {
1644 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1645 + struct ipn_network *ipnn=ipn_node->ipn;
1646 + void __user* argp = (void __user*)arg;
1649 + if (ipn_node->shutdown == SHUTDOWN_XMASK)
1650 + return -ECONNRESET;
1652 + /* get arguments */
1656 + case IPN_SETPERSIST_NETDEV:
1657 + case IPN_CLRPERSIST_NETDEV:
1658 + case IPN_CONN_NETDEV:
1659 + case IPN_JOIN_NETDEV:
1660 + case SIOCSIFHWADDR:
1661 + if (copy_from_user(&ifr, argp, sizeof ifr))
1663 + ifr.ifr_name[IFNAMSIZ-1] = '\0';
1666 + /* actions for unconnected and unbound sockets */
1668 + case IPN_SETPERSIST_NETDEV:
1669 + return ipn_setpersist_netdev(&ifr,1);
1670 + case IPN_CLRPERSIST_NETDEV:
1671 + return ipn_setpersist_netdev(&ifr,0);
1672 + case SIOCSIFHWADDR:
1673 + if (capable(CAP_NET_ADMIN))
1675 + if (ipn_node->dev && (ipn_node->flags &IPN_NODEFLAG_TAP))
1676 + return dev_set_mac_address(ipn_node->dev, &ifr.ifr_hwaddr);
1678 + return -EADDRNOTAVAIL;
1680 + if (ipnn == NULL || (ipnn->flags & IPN_FLAG_TERMINATED))
1682 + /* actions for connected or bound sockets */
1684 + case IPN_CONN_NETDEV:
1685 + return ipn_connect_netdev(sock,&ifr);
1686 + case IPN_JOIN_NETDEV:
1687 + return ipn_join_netdev(sock,&ifr);
1688 + case IPN_SETPERSIST:
1689 + return ipn_setpersist(ipn_node,arg);
1693 + if (down_interruptible(&ipnn->ipnn_mutex))
1694 + return -ERESTARTSYS;
1695 + rv=ipn_protocol_table[ipn_node->protocol]->ipn_p_ioctl(ipn_node,cmd,arg);
1696 + up(&ipnn->ipnn_mutex);
1699 + return -EOPNOTSUPP;
1703 +/* shutdown: close socket for input or for output.
1704 + * shutdown can be called prior to connect and it is not reversible */
1705 +static int ipn_shutdown(struct socket *sock, int mode) {
1706 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1707 + struct ipn_network *ipnn=ipn_node->ipn;
1708 + int oldshutdown=ipn_node->shutdown;
1709 + mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
1711 + ipn_node->shutdown |= mode;
1714 + if (down_interruptible(&ipnn->ipnn_mutex)) {
1715 + ipn_node->shutdown = oldshutdown;
1716 + return -ERESTARTSYS;
1718 + oldshutdown=ipn_node->shutdown-oldshutdown;
1719 + if (sock->state == SS_CONNECTED && oldshutdown) {
1720 + ipn_net_update_counters(ipnn,
1721 + (ipn_node->shutdown & RCV_SHUTDOWN)?0:-1,
1722 + (ipn_node->shutdown & SEND_SHUTDOWN)?0:-1);
1725 + /* if recv channel has been shut down, flush the recv queue */
1726 + if ((ipn_node->shutdown & RCV_SHUTDOWN))
1727 + ipn_flush_recvqueue(ipn_node);
1728 + up(&ipnn->ipnn_mutex);
1733 +/* injectmsg: a new message is entering the ipn network.
1734 + * injectmsg gets called by send and by the grab/tap node */
1735 +int ipn_proto_injectmsg(struct ipn_node *from, struct msgpool_item *msg)
1737 + struct ipn_network *ipnn=from->ipn;
1739 + if (down_interruptible(&ipnn->ipnn_mutex))
1742 + ipn_protocol_table[ipnn->protocol]->ipn_p_handlemsg(from, msg);
1743 + up(&ipnn->ipnn_mutex);
1749 +static int ipn_sendmsg(struct kiocb *kiocb, struct socket *sock,
1750 + struct msghdr *msg, size_t len) {
1751 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1752 + struct ipn_network *ipnn=ipn_node->ipn;
1753 + struct msgpool_item *newmsg;
1756 + if (unlikely(sock->state != SS_CONNECTED))
1758 + if (unlikely(ipn_node->shutdown & SEND_SHUTDOWN)) {
1759 + if (ipn_node->shutdown == SHUTDOWN_XMASK)
1760 + return -ECONNRESET;
1764 + if (len > ipnn->mtu)
1765 + return -EOVERFLOW;
1766 + newmsg=ipn_msgpool_alloc_locking(ipnn);
1770 + err=memcpy_fromiovec(newmsg->data, msg->msg_iov, len);
1772 + ipn_proto_injectmsg(ipn_node, newmsg);
1773 + ipn_msgpool_put(newmsg,ipnn);
1777 +/* enqueue an oob message. "to" is the destination */
1778 +void ipn_proto_oobsendmsg(struct ipn_node *to, struct msgpool_item *msg)
1781 + if (!to->dev) { /* no oob to netdev */
1782 + struct msgitem *msgitem;
1783 + struct ipn_network *ipnn=to->ipn;
1784 + spin_lock(&to->msglock);
1785 + if ((to->shutdown & RCV_SHUTDOWN_NO_OOB) == 0 &&
1786 + (ipnn->flags & IPN_FLAG_LOSSLESS ||
1787 + to->oobmsgcount < ipnn->msgpool_size)) {
1788 + if ((msgitem=kmem_cache_alloc(ipn_msgitem_cache,GFP_KERNEL))!=NULL) {
1790 + to->totmsgcount++;
1791 + to->oobmsgcount++;
1792 + list_add_tail(&msgitem->list, &to->oobmsgqueue);
1793 + ipn_msgpool_hold(msg);
1796 + spin_unlock(&to->msglock);
1797 + wake_up_interruptible(&to->read_wait);
1802 +/* ipn_proto_sendmsg is called by protocol implementation to enqueue a
1803 + * for a destination (to).*/
1804 +void ipn_proto_sendmsg(struct ipn_node *to, struct msgpool_item *msg)
1808 + ipn_netdev_sendmsg(to,msg);
1811 + struct msgitem *msgitem;
1812 + struct ipn_network *ipnn=to->ipn;
1813 + spin_lock(&to->msglock);
1814 + if (likely((to->shutdown & RCV_SHUTDOWN)==0)) {
1815 + /*if (unlikely((ipnn->flags & IPN_FLAG_LOSSLESS) == 0 ||
1816 + to->totmsgcount >= ipnn->msgpool_size))
1818 + if (likely(ipnn->flags & IPN_FLAG_LOSSLESS ||
1819 + to->totmsgcount < ipnn->msgpool_size)) {
1820 + if ((msgitem=kmem_cache_alloc(ipn_msgitem_cache,GFP_KERNEL))!=NULL) {
1822 + to->totmsgcount++;
1823 + list_add_tail(&msgitem->list, &to->msgqueue);
1824 + ipn_msgpool_hold(msg);
1828 + spin_unlock(&to->msglock);
1829 + wake_up_interruptible(&to->read_wait);
1835 +static int ipn_recvmsg(struct kiocb *kiocb, struct socket *sock,
1836 + struct msghdr *msg, size_t len, int flags) {
1837 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1838 + struct ipn_network *ipnn=ipn_node->ipn;
1839 + struct msgitem *msgitem;
1840 + struct msgpool_item *currmsg;
1842 + if (unlikely(sock->state != SS_CONNECTED))
1845 + if (unlikely((ipn_node->shutdown & XRCV_SHUTDOWN) == XRCV_SHUTDOWN)) {
1846 + if (ipn_node->shutdown == SHUTDOWN_XMASK) /*EOF, nothing can be read*/
1849 + return -EPIPE; /*trying to read on a write only node */
1852 + /* wait for a message */
1853 + spin_lock(&ipn_node->msglock);
1854 + while (ipn_node->totmsgcount == 0) {
1855 + spin_unlock(&ipn_node->msglock);
1856 + if (wait_event_interruptible(ipn_node->read_wait,
1857 + !(ipn_node->totmsgcount == 0)))
1858 + return -ERESTARTSYS;
1859 + spin_lock(&ipn_node->msglock);
1861 + /* oob gets delivered first. oob are rare */
1862 + if (likely(list_empty(&ipn_node->oobmsgqueue)))
1863 + msgitem=list_first_entry(&ipn_node->msgqueue, struct msgitem, list);
1865 + msgitem=list_first_entry(&ipn_node->oobmsgqueue, struct msgitem, list);
1866 + msg->msg_flags |= MSG_OOB;
1867 + ipn_node->oobmsgcount--;
1869 + list_del(&msgitem->list);
1870 + ipn_node->totmsgcount--;
1871 + spin_unlock(&ipn_node->msglock);
1872 + currmsg=msgitem->msg;
1873 + if (currmsg->len < len)
1875 + memcpy_toiovec(msg->msg_iov, currmsg->data, len);
1876 + ipn_msgpool_put(currmsg,ipnn);
1877 + kmem_cache_free(ipn_msgitem_cache,msgitem);
1882 +/* resize a network: change the # of communication ports (connport) */
1883 +static int ipn_netresize(struct ipn_network *ipnn,int newsize)
1886 + struct ipn_node **newconnport;
1887 + struct ipn_node **oldconnport;
1889 + if (down_interruptible(&ipnn->ipnn_mutex))
1890 + return -ERESTARTSYS;
1891 + oldsize=ipnn->maxports;
1892 + if (newsize == oldsize) {
1893 + up(&ipnn->ipnn_mutex);
1897 + /* shrink a network. all the ports we are going to eliminate
1898 + * must be unused! */
1899 + if (newsize < oldsize) {
1901 + for (i=newsize; i<oldsize; i++)
1902 + if (ipnn->connport[i]) {
1903 + up(&ipnn->ipnn_mutex);
1904 + return -EADDRINUSE;
1908 + oldconnport=ipnn->connport;
1909 + /* allocate the new connport array and copy the old one */
1910 + newconnport=kzalloc(newsize * sizeof(struct ipn_node *),GFP_KERNEL);
1911 + if (!newconnport) {
1912 + up(&ipnn->ipnn_mutex);
1915 + memcpy(newconnport,oldconnport,min * sizeof(struct ipn_node *));
1916 + ipnn->connport=newconnport;
1917 + ipnn->maxports=newsize;
1918 + /* notify the protocol that the netowrk has been resized */
1919 + err=ipn_protocol_table[ipnn->protocol]->ipn_p_resizenet(ipnn,oldsize,newsize);
1921 + /* roll back if the resize operation failed for the protocol */
1922 + ipnn->connport=oldconnport;
1923 + ipnn->maxports=oldsize;
1924 + kfree(newconnport);
1926 + /* successful mission, network resized */
1927 + kfree(oldconnport);
1928 + up(&ipnn->ipnn_mutex);
1932 +/* IPN SETSOCKOPT */
1933 +static int ipn_setsockopt(struct socket *sock, int level, int optname,
1934 + char __user *optval, int optlen) {
1935 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1936 + struct ipn_network *ipnn=ipn_node->ipn;
1938 + if (ipn_node->shutdown == SHUTDOWN_XMASK)
1939 + return -ECONNRESET;
1940 + if (level != 0 && level != ipn_node->protocol+1)
1941 + return -EPROTONOSUPPORT;
1943 + /* protocol specific sockopt */
1946 + if (down_interruptible(&ipnn->ipnn_mutex))
1947 + return -ERESTARTSYS;
1948 + rv=ipn_protocol_table[ipn_node->protocol]->ipn_p_setsockopt(ipn_node,optname,optval,optlen);
1949 + up(&ipnn->ipnn_mutex);
1952 + return -EOPNOTSUPP;
1954 + if (optname == IPN_SO_DESCR) {
1955 + if (optlen > IPN_DESCRLEN)
1958 + memset(ipn_node->descr,0,IPN_DESCRLEN);
1959 + if (copy_from_user(ipn_node->descr,optval,optlen))
1960 + ipn_node->descr[0]=0;
1962 + ipn_node->descr[optlen-1]=0;
1966 + if (optlen < sizeof(int))
1968 + else if ((optname & IPN_SO_PREBIND) && (ipnn != NULL))
1972 + get_user(val, (int __user *) optval);
1973 + if ((optname & IPN_SO_PREBIND) && !ipn_node->pbp) {
1974 + struct pre_bind_parms std=STD_BIND_PARMS;
1975 + ipn_node->pbp=kzalloc(sizeof(struct pre_bind_parms),GFP_KERNEL);
1976 + if (!ipn_node->pbp)
1978 + *(ipn_node->pbp)=std;
1980 + switch (optname) {
1982 + if (sock->state == SS_UNCONNECTED)
1983 + ipn_node->portno=val;
1987 + case IPN_SO_CHANGE_NUMNODES:
1988 + if ((ipn_node->flags & IPN_NODEFLAG_BOUND)!=0) {
1992 + return ipn_netresize(ipnn,val);
1996 + case IPN_SO_WANT_OOB_NUMNODES:
1998 + ipn_node->flags |= IPN_NODEFLAG_OOB_NUMNODES;
2000 + ipn_node->flags &= ~IPN_NODEFLAG_OOB_NUMNODES;
2002 + case IPN_SO_HANDLE_OOB:
2004 + ipn_node->shutdown &= ~RCV_SHUTDOWN_NO_OOB;
2006 + ipn_node->shutdown |= RCV_SHUTDOWN_NO_OOB;
2012 + ipn_node->pbp->mtu=val;
2014 + case IPN_SO_NUMNODES:
2018 + ipn_node->pbp->maxports=val;
2020 + case IPN_SO_MSGPOOLSIZE:
2024 + ipn_node->pbp->msgpoolsize=val;
2026 + case IPN_SO_FLAGS:
2027 + ipn_node->pbp->flags=val;
2030 + ipn_node->pbp->mode=val;
2039 +/* IPN GETSOCKOPT */
2040 +static int ipn_getsockopt(struct socket *sock, int level, int optname,
2041 + char __user *optval, int __user *optlen) {
2042 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
2043 + struct ipn_network *ipnn=ipn_node->ipn;
2046 + if (ipn_node->shutdown == SHUTDOWN_XMASK)
2047 + return -ECONNRESET;
2048 + if (level != 0 && level != ipn_node->protocol+1)
2049 + return -EPROTONOSUPPORT;
2053 + /* protocol specific sockopt */
2054 + if (down_interruptible(&ipnn->ipnn_mutex))
2055 + return -ERESTARTSYS;
2056 + rv=ipn_protocol_table[ipn_node->protocol]->ipn_p_getsockopt(ipn_node,optname,optval,optlen);
2057 + up(&ipnn->ipnn_mutex);
2060 + return -EOPNOTSUPP;
2062 + if (get_user(len, optlen))
2064 + if (optname == IPN_SO_DESCR) {
2065 + if (len < IPN_DESCRLEN)
2068 + if (len > IPN_DESCRLEN)
2070 + if(put_user(len, optlen))
2072 + if(copy_to_user(optval,ipn_node->descr,len))
2078 + switch (optname) {
2080 + val=ipn_node->portno;
2085 + else if (ipn_node->pbp)
2086 + val=ipn_node->pbp->mtu;
2088 + case IPN_SO_NUMNODES:
2090 + val=ipnn->maxports;
2091 + else if (ipn_node->pbp)
2092 + val=ipn_node->pbp->maxports;
2094 + case IPN_SO_MSGPOOLSIZE:
2096 + val=ipnn->msgpool_size;
2097 + else if (ipn_node->pbp)
2098 + val=ipn_node->pbp->msgpoolsize;
2100 + case IPN_SO_FLAGS:
2103 + else if (ipn_node->pbp)
2104 + val=ipn_node->pbp->flags;
2109 + else if (ipn_node->pbp)
2110 + val=ipn_node->pbp->mode;
2116 + if (len < sizeof(int))
2117 + return -EOVERFLOW;
2119 + len = sizeof(int);
2120 + if(put_user(len, optlen))
2122 + if(copy_to_user(optval,&val,len))
2131 +/* BROADCAST/HUB implementation */
2133 +static int ipn_bcast_newport(struct ipn_node *newport) {
2134 + struct ipn_network *ipnn=newport->ipn;
2136 + for (i=0;i<ipnn->maxports;i++) {
2137 + if (ipnn->connport[i] == NULL)
2143 +static int ipn_bcast_handlemsg(struct ipn_node *from,
2144 + struct msgpool_item *msgitem){
2145 + struct ipn_network *ipnn=from->ipn;
2147 + struct ipn_node *ipn_node;
2148 + list_for_each_entry(ipn_node, &ipnn->connectqueue, nodelist) {
2149 + if (ipn_node != from)
2150 + ipn_proto_sendmsg(ipn_node,msgitem);
2155 +static void ipn_null_delport(struct ipn_node *oldport) {}
2156 +static void ipn_null_postnewport(struct ipn_node *newport) {}
2157 +static void ipn_null_predelport(struct ipn_node *oldport) {}
2158 +static int ipn_null_newnet(struct ipn_network *newnet) {return 0;}
2159 +static int ipn_null_resizenet(struct ipn_network *net,int oldsize,int newsize) {
2161 +static void ipn_null_delnet(struct ipn_network *oldnet) {}
2162 +static int ipn_null_setsockopt(struct ipn_node *port,int optname,
2163 + char __user *optval, int optlen) {return -EOPNOTSUPP;}
2164 +static int ipn_null_getsockopt(struct ipn_node *port,int optname,
2165 + char __user *optval, int *optlen) {return -EOPNOTSUPP;}
2166 +static int ipn_null_ioctl(struct ipn_node *port,unsigned int request,
2167 + unsigned long arg) {return -EOPNOTSUPP;}
2169 +/* Protocol Registration/deregisteration */
2171 +void ipn_init_protocol(struct ipn_protocol *p)
2173 + if (p->ipn_p_delport == NULL) p->ipn_p_delport=ipn_null_delport;
2174 + if (p->ipn_p_postnewport == NULL) p->ipn_p_postnewport=ipn_null_postnewport;
2175 + if (p->ipn_p_predelport == NULL) p->ipn_p_predelport=ipn_null_predelport;
2176 + if (p->ipn_p_newnet == NULL) p->ipn_p_newnet=ipn_null_newnet;
2177 + if (p->ipn_p_resizenet == NULL) p->ipn_p_resizenet=ipn_null_resizenet;
2178 + if (p->ipn_p_delnet == NULL) p->ipn_p_delnet=ipn_null_delnet;
2179 + if (p->ipn_p_setsockopt == NULL) p->ipn_p_setsockopt=ipn_null_setsockopt;
2180 + if (p->ipn_p_getsockopt == NULL) p->ipn_p_getsockopt=ipn_null_getsockopt;
2181 + if (p->ipn_p_ioctl == NULL) p->ipn_p_ioctl=ipn_null_ioctl;
2184 +int ipn_proto_register(int protocol,struct ipn_protocol *ipn_service)
2187 + if (ipn_service->ipn_p_newport == NULL ||
2188 + ipn_service->ipn_p_handlemsg == NULL)
2190 + ipn_init_protocol(ipn_service);
2191 + if (down_interruptible(&ipn_glob_mutex))
2192 + return -ERESTARTSYS;
2193 + if (protocol > 1 && protocol <= IPN_MAX_PROTO) {
2195 + if (ipn_protocol_table[protocol])
2198 + ipn_service->refcnt=0;
2199 + ipn_protocol_table[protocol]=ipn_service;
2200 + printk(KERN_INFO "IPN: Registered protocol %d\n",protocol+1);
2204 + up(&ipn_glob_mutex);
2208 +int ipn_proto_deregister(int protocol)
2211 + if (down_interruptible(&ipn_glob_mutex))
2212 + return -ERESTARTSYS;
2213 + if (protocol > 1 && protocol <= IPN_MAX_PROTO) {
2215 + if (ipn_protocol_table[protocol]) {
2216 + if (ipn_protocol_table[protocol]->refcnt == 0) {
2217 + ipn_protocol_table[protocol]=NULL;
2218 + printk(KERN_INFO "IPN: Unregistered protocol %d\n",protocol+1);
2225 + up(&ipn_glob_mutex);
2230 +/* Module constructor/destructor */
2231 +static struct net_proto_family ipn_family_ops = {
2233 + .create = ipn_create,
2234 + .owner = THIS_MODULE,
2237 +/* IPN constructor */
2238 +static int ipn_init(void)
2242 + ipn_init_protocol(&ipn_bcast);
2243 + ipn_network_cache=kmem_cache_create("ipn_network",sizeof(struct ipn_network),0,0,NULL);
2244 + if (!ipn_network_cache) {
2245 + printk(KERN_CRIT "%s: Cannot create ipn_network SLAB cache!\n",
2251 + ipn_node_cache=kmem_cache_create("ipn_node",sizeof(struct ipn_node),0,0,NULL);
2252 + if (!ipn_node_cache) {
2253 + printk(KERN_CRIT "%s: Cannot create ipn_node SLAB cache!\n",
2259 + ipn_msgitem_cache=kmem_cache_create("ipn_msgitem",sizeof(struct msgitem),0,0,NULL);
2260 + if (!ipn_msgitem_cache) {
2261 + printk(KERN_CRIT "%s: Cannot create ipn_msgitem SLAB cache!\n",
2264 + goto out_net_node;
2267 + rc=ipn_msgbuf_init();
2269 + printk(KERN_CRIT "%s: Cannot create ipn_msgbuf SLAB cache\n",
2271 + goto out_net_node_msg;
2274 + rc=proto_register(&ipn_proto,1);
2276 + printk(KERN_CRIT "%s: Cannot register the protocol!\n",
2278 + goto out_net_node_msg_msgbuf;
2281 + sock_register(&ipn_family_ops);
2282 + ipn_netdev_init();
2283 + printk(KERN_INFO "IPN: Virtual Square Project, University of Bologna 2007\n");
2286 +out_net_node_msg_msgbuf:
2287 + ipn_msgbuf_fini();
2289 + kmem_cache_destroy(ipn_msgitem_cache);
2291 + kmem_cache_destroy(ipn_node_cache);
2293 + kmem_cache_destroy(ipn_network_cache);
2298 +/* IPN destructor */
2299 +static void ipn_exit(void)
2301 + ipn_netdev_fini();
2302 + if (ipn_msgitem_cache)
2303 + kmem_cache_destroy(ipn_msgitem_cache);
2304 + if (ipn_node_cache)
2305 + kmem_cache_destroy(ipn_node_cache);
2306 + if (ipn_network_cache)
2307 + kmem_cache_destroy(ipn_network_cache);
2308 + ipn_msgbuf_fini();
2309 + sock_unregister(PF_IPN);
2310 + proto_unregister(&ipn_proto);
2311 + printk(KERN_INFO "IPN removed\n");
2314 +module_init(ipn_init);
2315 +module_exit(ipn_exit);
2317 +EXPORT_SYMBOL_GPL(ipn_proto_register);
2318 +EXPORT_SYMBOL_GPL(ipn_proto_deregister);
2319 +EXPORT_SYMBOL_GPL(ipn_proto_sendmsg);
2320 +EXPORT_SYMBOL_GPL(ipn_proto_oobsendmsg);
2321 +EXPORT_SYMBOL_GPL(ipn_msgpool_alloc);
2322 +EXPORT_SYMBOL_GPL(ipn_msgpool_put);
2323 diff -Naur linux-2.6.25.4/net/ipn/ipn_msgbuf.c linux-2.6.25.4-ipn/net/ipn/ipn_msgbuf.c
2324 --- linux-2.6.25.4/net/ipn/ipn_msgbuf.c 1970-01-01 01:00:00.000000000 +0100
2325 +++ linux-2.6.25.4-ipn/net/ipn/ipn_msgbuf.c 2008-05-31 15:27:52.000000000 +0200
2328 + * Inter process networking (virtual distributed ethernet) module
2329 + * management of ipn_msgbuf (one slab for each MTU)
2330 + * (part of the View-OS project: wiki.virtualsquare.org)
2332 + * N.B. all these functions need global locking! (ipn_glob_lock)
2334 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
2336 + * This program is free software; you can redistribute it and/or modify
2337 + * it under the terms of the GNU General Public License as published by
2338 + * the Free Software Foundation; either version 2 of the License, or
2339 + * (at your option) any later version.
2341 + * Due to this file being licensed under the GPL there is controversy over
2342 + * whether this permits you to write a module that #includes this file
2343 + * without placing your module under the GPL. Please consult a lawyer for
2344 + * advice before doing this.
2346 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2350 +#include <linux/init.h>
2351 +#include <linux/module.h>
2353 +#include <net/af_ipn.h>
2354 +#include "ipn_netdev.h"
2356 +struct ipn_msgbuf {
2357 + struct list_head list;
2360 + char cachename[12];
2361 + struct kmem_cache *cache;
2364 +static LIST_HEAD(ipn_msgbufh);
2365 +static struct kmem_cache *ipn_msgbuf_cache;
2367 +/* get a kmem_cache pointer for a given mtu.
2368 + * it is a cache for struct msgpool_item elements (the latter field of
2369 + * the struct, i.e. the payload, has variable length depending on the mtu)
2370 + * if it exists already a cache with the given mtu, ipn_msgbuf_get creates
2371 + * one more reference for that cache, otherwise a new one is created.
2373 +struct kmem_cache *ipn_msgbuf_get(int mtu)
2375 + struct ipn_msgbuf *ipn_msgbuf;
2376 + list_for_each_entry(ipn_msgbuf, &ipn_msgbufh, list) {
2377 + if (mtu == ipn_msgbuf->mtu) {
2378 + ipn_msgbuf->refcnt++;
2379 + return ipn_msgbuf->cache;
2382 + ipn_msgbuf=kmem_cache_alloc(ipn_msgbuf_cache,GFP_KERNEL);
2383 + if (ipn_msgbuf == NULL)
2386 + ipn_msgbuf->mtu=mtu;
2387 + ipn_msgbuf->refcnt=1;
2388 + snprintf(ipn_msgbuf->cachename,12,"ipn%d",mtu);
2389 + ipn_msgbuf->cache=kmem_cache_create(ipn_msgbuf->cachename,sizeof(struct msgpool_item)+mtu,0,0,NULL);
2390 + list_add_tail(&ipn_msgbuf->list,&ipn_msgbufh);
2391 + return ipn_msgbuf->cache;
2395 +/* release a reference of a msgbuf cache (a network with a given mtu
2396 + * is terminating).
2397 + * the last reference for a given mtu releases the slub*/
2398 +void ipn_msgbuf_put(struct kmem_cache *cache)
2400 + struct ipn_msgbuf *ipn_msgbuf;
2401 + list_for_each_entry(ipn_msgbuf, &ipn_msgbufh, list) {
2402 + if (ipn_msgbuf->cache == cache) {
2403 + ipn_msgbuf->refcnt--;
2404 + if (ipn_msgbuf->refcnt == 0) {
2405 + kmem_cache_destroy(ipn_msgbuf->cache);
2406 + list_del(&ipn_msgbuf->list);
2407 + kmem_cache_free(ipn_msgbuf_cache,ipn_msgbuf);
2414 +int ipn_msgbuf_init(void)
2416 + ipn_msgbuf_cache=kmem_cache_create("ipn_msgbuf",sizeof(struct ipn_msgbuf),0,0,NULL);
2417 + if (!ipn_msgbuf_cache)
2423 +void ipn_msgbuf_fini(void)
2425 + if (ipn_msgbuf_cache) {
2426 + while (!list_empty(&ipn_msgbufh)) {
2427 + struct ipn_msgbuf *ipn_msgbuf=list_first_entry(&ipn_msgbufh, struct ipn_msgbuf, list);
2428 + list_del(&ipn_msgbuf->list);
2429 + kmem_cache_destroy(ipn_msgbuf->cache);
2430 + kmem_cache_free(ipn_msgbuf_cache,ipn_msgbuf);
2432 + kmem_cache_destroy(ipn_msgbuf_cache);
2435 diff -Naur linux-2.6.25.4/net/ipn/ipn_msgbuf.h linux-2.6.25.4-ipn/net/ipn/ipn_msgbuf.h
2436 --- linux-2.6.25.4/net/ipn/ipn_msgbuf.h 1970-01-01 01:00:00.000000000 +0100
2437 +++ linux-2.6.25.4-ipn/net/ipn/ipn_msgbuf.h 2008-05-31 15:27:52.000000000 +0200
2440 + * Inter process networking (virtual distributed ethernet) module
2441 + * management of msgbuf (one slab for each MTU)
2442 + * (part of the View-OS project: wiki.virtualsquare.org)
2444 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
2446 + * This program is free software; you can redistribute it and/or modify
2447 + * it under the terms of the GNU General Public License as published by
2448 + * the Free Software Foundation; either version 2 of the License, or
2449 + * (at your option) any later version.
2451 + * Due to this file being licensed under the GPL there is controversy over
2452 + * whether this permits you to write a module that #includes this file
2453 + * without placing your module under the GPL. Please consult a lawyer for
2454 + * advice before doing this.
2456 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2460 +#ifndef _IPN_MSGBUF_H
2461 +#define _IPN_MSGBUF_H
2463 +struct kmem_cache *ipn_msgbuf_get(int mtu);
2464 +void ipn_msgbuf_put(struct kmem_cache *cache);
2465 +int ipn_msgbuf_init(void);
2466 +void ipn_msgbuf_fini(void);
2469 diff -Naur linux-2.6.25.4/net/ipn/ipn_netdev.c linux-2.6.25.4-ipn/net/ipn/ipn_netdev.c
2470 --- linux-2.6.25.4/net/ipn/ipn_netdev.c 1970-01-01 01:00:00.000000000 +0100
2471 +++ linux-2.6.25.4-ipn/net/ipn/ipn_netdev.c 2008-05-31 15:27:52.000000000 +0200
2474 + * Inter process networking (virtual distributed ethernet) module
2475 + * Net devices: tap and grab
2476 + * (part of the View-OS project: wiki.virtualsquare.org)
2478 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
2480 + * This program is free software; you can redistribute it and/or modify
2481 + * it under the terms of the GNU General Public License as published by
2482 + * the Free Software Foundation; either version 2 of the License, or
2483 + * (at your option) any later version.
2485 + * Due to this file being licensed under the GPL there is controversy over
2486 + * whether this permits you to write a module that #includes this file
2487 + * without placing your module under the GPL. Please consult a lawyer for
2488 + * advice before doing this.
2490 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2494 +#include <linux/init.h>
2495 +#include <linux/module.h>
2496 +#include <linux/socket.h>
2497 +#include <linux/poll.h>
2498 +#include <linux/un.h>
2499 +#include <linux/list.h>
2500 +#include <linux/mount.h>
2501 +#include <linux/etherdevice.h>
2502 +#include <linux/ethtool.h>
2503 +#include <linux/version.h>
2504 +#include <net/sock.h>
2505 +#include <net/af_ipn.h>
2506 +#include "ipn_netdev.h"
2508 +#define DRV_NAME "ipn"
2509 +#define DRV_VERSION "0.3"
2511 +static const struct ethtool_ops ipn_ethtool_ops;
2514 + struct ipn_node *ipn_node;
2515 + struct net_device_stats stats;
2518 +/* TAP Net device open. */
2519 +static int ipntap_net_open(struct net_device *dev)
2521 + netif_start_queue(dev);
2525 +/* TAP Net device close. */
2526 +static int ipntap_net_close(struct net_device *dev)
2528 + netif_stop_queue(dev);
2532 +static struct net_device_stats *ipntap_net_stats(struct net_device *dev)
2534 + struct ipntap *ipntap = netdev_priv(dev);
2535 + return &ipntap->stats;
2538 +/* receive from a TAP */
2539 +static int ipn_net_xmit(struct sk_buff *skb, struct net_device *dev)
2541 + struct ipntap *ipntap = netdev_priv(dev);
2542 + struct ipn_node *ipn_node=ipntap->ipn_node;
2543 + struct msgpool_item *newmsg;
2544 + if (!ipn_node || !ipn_node->ipn || skb->len > ipn_node->ipn->mtu)
2546 + newmsg=ipn_msgpool_alloc(ipn_node->ipn,1);
2549 + newmsg->len=skb->len;
2550 + memcpy(newmsg->data,skb->data,skb->len);
2551 + ipn_proto_injectmsg(ipntap->ipn_node,newmsg);
2552 + ipn_msgpool_put(newmsg,ipn_node->ipn);
2553 + ipntap->stats.tx_packets++;
2554 + ipntap->stats.tx_bytes += skb->len;
2559 + ipntap->stats.tx_dropped++;
2564 +/* receive from a GRAB via interface hook */
2565 +struct sk_buff *ipn_handle_hook(struct ipn_node *ipn_node, struct sk_buff *skb)
2567 + char *data=(skb->data)-(skb->mac_len);
2568 + int len=skb->len+skb->mac_len;
2571 + ((ipn_node->flags & IPN_NODEFLAG_DEVMASK) == IPN_NODEFLAG_GRAB) &&
2572 + ipn_node->ipn && len<=ipn_node->ipn->mtu) {
2573 + struct msgpool_item *newmsg;
2574 + newmsg=ipn_msgpool_alloc(ipn_node->ipn,1);
2577 + memcpy(newmsg->data,data,len);
2578 + ipn_proto_injectmsg(ipn_node,newmsg);
2579 + ipn_msgpool_put(newmsg,ipn_node->ipn);
2586 +static void ipntap_setup(struct net_device *dev)
2588 + dev->open = ipntap_net_open;
2589 + dev->hard_start_xmit = ipn_net_xmit;
2590 + dev->stop = ipntap_net_close;
2591 + dev->get_stats = ipntap_net_stats;
2592 + dev->ethtool_ops = &ipn_ethtool_ops;
2596 +struct net_device *ipn_netdev_alloc(struct net *net,int type, char *name, int *err)
2598 + struct net_device *dev=NULL;
2600 + if (!name || *name==0)
2603 + case IPN_NODEFLAG_TAP:
2604 + dev=alloc_netdev(sizeof(struct ipntap), name, ipntap_setup);
2608 + /* this commented code is similar to tuntap MAC assignment.
2609 + * why tuntap does not use the random_ether_addr?
2610 + *(u16 *)dev->dev_addr = htons(0x00FF);
2611 + get_random_bytes(dev->dev_addr + sizeof(u16), 4);*/
2612 + random_ether_addr((u8 *)&dev->dev_addr);
2614 + case IPN_NODEFLAG_GRAB:
2615 + dev=dev_get_by_name(net,name);
2617 + if (dev->flags & IFF_LOOPBACK)
2619 + else if (rcu_dereference(dev->ipn_port) != NULL)
2629 +int ipn_netdev_activate(struct ipn_node *ipn_node)
2632 + switch (ipn_node->flags & IPN_NODEFLAG_DEVMASK) {
2633 + case IPN_NODEFLAG_TAP:
2635 + struct ipntap *ipntap=netdev_priv(ipn_node->dev);
2636 + ipntap->ipn_node=ipn_node;
2638 + if ((rv=register_netdevice(ipn_node->dev)) == 0)
2639 + rcu_assign_pointer(ipn_node->dev->ipn_port,
2642 + if (rv) {/* error! */
2643 + ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
2644 + free_netdev(ipn_node->dev);
2648 + case IPN_NODEFLAG_GRAB:
2650 + rcu_assign_pointer(ipn_node->dev->ipn_port,
2652 + dev_set_promiscuity(ipn_node->dev,1);
2660 +void ipn_netdev_close(struct ipn_node *ipn_node)
2662 + switch (ipn_node->flags & IPN_NODEFLAG_DEVMASK) {
2663 + case IPN_NODEFLAG_TAP:
2664 + ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
2666 + rcu_assign_pointer(ipn_node->dev->ipn_port, NULL);
2667 + unregister_netdevice(ipn_node->dev);
2669 + free_netdev(ipn_node->dev);
2671 + case IPN_NODEFLAG_GRAB:
2672 + ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
2674 + rcu_assign_pointer(ipn_node->dev->ipn_port, NULL);
2675 + dev_set_promiscuity(ipn_node->dev,-1);
2681 +void ipn_netdev_sendmsg(struct ipn_node *to,struct msgpool_item *msg)
2683 + struct sk_buff *skb;
2684 + struct net_device *dev=to->dev;
2685 + struct ipntap *ipntap=netdev_priv(dev);
2687 + if (msg->len > dev->mtu)
2689 + skb=alloc_skb(msg->len+NET_IP_ALIGN,GFP_KERNEL);
2691 + ipntap->stats.rx_dropped++;
2694 + memcpy(skb_put(skb,msg->len),msg->data,msg->len);
2695 + switch (to->flags & IPN_NODEFLAG_DEVMASK) {
2696 + case IPN_NODEFLAG_TAP:
2697 + skb->protocol = eth_type_trans(skb, dev);
2699 + ipntap->stats.rx_packets++;
2700 + ipntap->stats.rx_bytes += msg->len;
2702 + case IPN_NODEFLAG_GRAB:
2704 + dev_queue_xmit(skb);
2709 +/* ethtool interface */
2711 +static int ipn_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
2713 + cmd->supported = 0;
2714 + cmd->advertising = 0;
2715 + cmd->speed = SPEED_10;
2716 + cmd->duplex = DUPLEX_FULL;
2717 + cmd->port = PORT_TP;
2718 + cmd->phy_address = 0;
2719 + cmd->transceiver = XCVR_INTERNAL;
2720 + cmd->autoneg = AUTONEG_DISABLE;
2721 + cmd->maxtxpkt = 0;
2722 + cmd->maxrxpkt = 0;
2726 +static void ipn_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
2728 + strcpy(info->driver, DRV_NAME);
2729 + strcpy(info->version, DRV_VERSION);
2730 + strcpy(info->fw_version, "N/A");
2733 +static const struct ethtool_ops ipn_ethtool_ops = {
2734 + .get_settings = ipn_get_settings,
2735 + .get_drvinfo = ipn_get_drvinfo,
2736 + /* not implemented (yet?)
2737 + .get_msglevel = ipn_get_msglevel,
2738 + .set_msglevel = ipn_set_msglevel,
2739 + .get_link = ipn_get_link,
2740 + .get_rx_csum = ipn_get_rx_csum,
2741 + .set_rx_csum = ipn_set_rx_csum */
2744 +int ipn_netdev_init(void)
2746 + ipn_handle_frame_hook=
2747 +#ifdef IPN_STEALING
2755 +void ipn_netdev_fini(void)
2757 + ipn_handle_frame_hook=NULL;
2759 diff -Naur linux-2.6.25.4/net/ipn/ipn_netdev.h linux-2.6.25.4-ipn/net/ipn/ipn_netdev.h
2760 --- linux-2.6.25.4/net/ipn/ipn_netdev.h 1970-01-01 01:00:00.000000000 +0100
2761 +++ linux-2.6.25.4-ipn/net/ipn/ipn_netdev.h 2008-05-31 15:27:52.000000000 +0200
2763 +#ifndef _IPN_NETDEV_H
2764 +#define _IPN_NETDEV_H
2766 + * Inter process networking (virtual distributed ethernet) module
2767 + * Net devices: tap and grab
2768 + * (part of the View-OS project: wiki.virtualsquare.org)
2770 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
2772 + * This program is free software; you can redistribute it and/or modify
2773 + * it under the terms of the GNU General Public License as published by
2774 + * the Free Software Foundation; either version 2 of the License, or
2775 + * (at your option) any later version.
2777 + * Due to this file being licensed under the GPL there is controversy over
2778 + * whether this permits you to write a module that #includes this file
2779 + * without placing your module under the GPL. Please consult a lawyer for
2780 + * advice before doing this.
2782 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2786 +#include <linux/init.h>
2787 +#include <linux/module.h>
2788 +#include <linux/socket.h>
2789 +#include <linux/poll.h>
2790 +#include <linux/un.h>
2791 +#include <linux/list.h>
2792 +#include <linux/mount.h>
2793 +#include <linux/etherdevice.h>
2794 +#include <linux/if_bridge.h>
2795 +#include <net/sock.h>
2796 +#include <net/af_ipn.h>
2798 +#ifdef IPN_STEALING
2799 +#define ipn_port br_port
2802 +struct net_device *ipn_netdev_alloc(struct net *net,int type, char *name, int *err);
2803 +int ipn_netdev_activate(struct ipn_node *ipn_node);
2804 +void ipn_netdev_close(struct ipn_node *ipn_node);
2805 +void ipn_netdev_sendmsg(struct ipn_node *to,struct msgpool_item *msg);
2806 +int ipn_netdev_init(void);
2807 +void ipn_netdev_fini(void);
2809 +static inline struct ipn_node *ipn_netdev2node(struct net_device *dev)
2811 + return (struct ipn_node *)rcu_dereference(dev->ipn_port);
2814 +static inline void ipn_netdevsync(void)
2816 + synchronize_rcu();