1 diff -Naur linux-2.6.28.2/Documentation/networking/ipn.txt linux-2.6.28.2-ipn/Documentation/networking/ipn.txt
2 --- linux-2.6.28.2/Documentation/networking/ipn.txt 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.28.2-ipn/Documentation/networking/ipn.txt 2009-02-01 13:29:48.000000000 +0100
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.
316 +More info and examples here: wiki.virtualsquare.org
317 +Note: waiting for the official assignment of a specific Address Family
318 +IPN is currently using AF_NETBEUI (unimplemented at the moment).
319 +AF_NETBEUI is 13, but we are not superstitious!
320 diff -Naur linux-2.6.28.2/MAINTAINERS linux-2.6.28.2-ipn/MAINTAINERS
321 --- linux-2.6.28.2/MAINTAINERS 2009-01-25 01:42:07.000000000 +0100
322 +++ linux-2.6.28.2-ipn/MAINTAINERS 2009-02-01 13:29:48.000000000 +0100
323 @@ -2378,6 +2378,15 @@
325 T: git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git
327 +IPN INTER PROCESS NETWORKING
329 +M: renzo@cs.unibo.it
330 +P: Ludovico Gardenghi
331 +M: garden@cs.unibo.it
332 +L: netdev@vger.kernel.org
333 +W: http://wiki.virtualsquare.org
337 P: Arnaldo Carvalho de Melo
338 M: acme@ghostprotocols.net
339 diff -Naur linux-2.6.28.2/include/linux/netdevice.h linux-2.6.28.2-ipn/include/linux/netdevice.h
340 --- linux-2.6.28.2/include/linux/netdevice.h 2009-01-25 01:42:07.000000000 +0100
341 +++ linux-2.6.28.2-ipn/include/linux/netdevice.h 2009-02-01 13:30:05.000000000 +0100
343 struct net_bridge_port *br_port;
345 struct macvlan_port *macvlan_port;
347 + struct ipn_node *ipn_port;
350 struct garp_port *garp_port;
352 diff -Naur linux-2.6.28.2/include/linux/socket.h linux-2.6.28.2-ipn/include/linux/socket.h
353 --- linux-2.6.28.2/include/linux/socket.h 2009-01-25 01:42:07.000000000 +0100
354 +++ linux-2.6.28.2-ipn/include/linux/socket.h 2009-02-01 13:30:05.000000000 +0100
356 #define PF_PHONET AF_PHONET
357 #define PF_MAX AF_MAX
359 +/* IPN stealing mode, waiting for an officially assigned AF */
360 +#define AF_IPN AF_NETBEUI
361 +#define PF_IPN AF_IPN
363 /* Maximum queue length specifiable by listen. */
364 #define SOMAXCONN 128
366 diff -Naur linux-2.6.28.2/include/net/af_ipn.h linux-2.6.28.2-ipn/include/net/af_ipn.h
367 --- linux-2.6.28.2/include/net/af_ipn.h 1970-01-01 01:00:00.000000000 +0100
368 +++ linux-2.6.28.2-ipn/include/net/af_ipn.h 2009-02-01 13:30:05.000000000 +0100
370 +#ifndef __LINUX_NET_AFIPN_H
371 +#define __LINUX_NET_AFIPN_H
374 +#define IPN_BROADCAST 1
376 +#define IPN_VDESWITCH 2
377 +#define IPN_VDESWITCH_L3 3
379 +#define IPN_SO_PREBIND 0x80
380 +#define IPN_SO_PORT 0
381 +#define IPN_SO_DESCR 1
382 +#define IPN_SO_CHANGE_NUMNODES 2
383 +#define IPN_SO_HANDLE_OOB 3
384 +#define IPN_SO_WANT_OOB_NUMNODES 4
385 +#define IPN_SO_MTU (IPN_SO_PREBIND | 0)
386 +#define IPN_SO_NUMNODES (IPN_SO_PREBIND | 1)
387 +#define IPN_SO_MSGPOOLSIZE (IPN_SO_PREBIND | 2)
388 +#define IPN_SO_FLAGS (IPN_SO_PREBIND | 3)
389 +#define IPN_SO_MODE (IPN_SO_PREBIND | 4)
391 +#define IPN_PORTNO_ANY -1
393 +#define IPN_DESCRLEN 128
395 +#define IPN_FLAG_LOSSLESS 1
396 +#define IPN_FLAG_EXCL 2
397 +#define IPN_FLAG_TERMINATED 0x1000
400 +#define IPN_CHECK _IOW('I', 199, int)
401 +#define IPN_SETPERSIST_NETDEV _IOW('I', 200, int)
402 +#define IPN_CLRPERSIST_NETDEV _IOW('I', 201, int)
403 +#define IPN_CONN_NETDEV _IOW('I', 202, int)
404 +#define IPN_JOIN_NETDEV _IOW('I', 203, int)
405 +#define IPN_SETPERSIST _IOW('I', 204, int)
407 +#define IPN_OOB_NUMNODE_TAG 0
409 +/* OOB message for change of numnodes
410 + * Common fields for oob IPN signaling:
411 + * @level=level of the service who generated the oob
412 + * @tag=tag of the message
414 + * @numreaders=number of readers
415 + * @numwriters=number of writers
417 +struct numnode_oob {
425 +#include <linux/socket.h>
426 +#include <linux/mutex.h>
427 +#include <linux/un.h>
428 +#include <net/sock.h>
429 +#include <linux/netdevice.h>
431 +#define IPN_HASH_SIZE 256
433 +/* The AF_IPN socket */
434 +struct msgpool_item;
436 +struct pre_bind_parms;
441 + * @nodelist=pointers for connectqueue or unconnectqueue (see network)
442 + * @protocol=kind of service 0->standard broadcast
443 + * @flags= see IPN_NODEFLAG_xxx
444 + * @shutdown= SEND_SHUTDOWN/RCV_SHUTDOWN and OOBRCV_SHUTDOWN
445 + * @descr=description of this port
446 + * @portno=when connected: port of the netowrk (<0 means unconnected)
447 + * @msglock=mutex on the msg queue
448 + * @totmsgcount=total # of pending msgs
449 + * @oobmsgcount=# of pending oob msgs
450 + * @msgqueue=queue of messages
451 + * @oobmsgqueue=queue of messages
452 + * @read_wait=waitqueue for reading
453 + * @net=current network
454 + * @dev=device (TAP or GRAB)
455 + * @ipn=network we are connected to
456 + * @pbp=temporary storage for parms that must be set prior to bind
457 + * @proto_private=handle for protocol private data
460 + struct list_head nodelist;
462 + volatile unsigned char flags;
463 + unsigned char shutdown;
464 + char descr[IPN_DESCRLEN];
466 + spinlock_t msglock;
467 + unsigned short totmsgcount;
468 + unsigned short oobmsgcount;
469 + struct list_head msgqueue;
470 + struct list_head oobmsgqueue;
471 + wait_queue_head_t read_wait;
473 + struct net_device *dev;
474 + struct ipn_network *ipn;
475 + struct pre_bind_parms *pbp;
476 + void *proto_private;
479 +#define IPN_NODEFLAG_BOUND 0x1 /* bind succeeded */
480 +#define IPN_NODEFLAG_INUSE 0x2 /* is currently "used" (0 for persistent, unbound interfaces) */
481 +#define IPN_NODEFLAG_PERSIST 0x4 /* if persist does not disappear on close (net interfaces) */
482 +#define IPN_NODEFLAG_TAP 0x10 /* This is a tap interface */
483 +#define IPN_NODEFLAG_GRAB 0x20 /* This is a grab of a real interface */
484 +#define IPN_NODEFLAG_DEVMASK 0x30 /* True if this is a device */
485 +#define IPN_NODEFLAG_OOB_NUMNODES 0x40 /* Node wants OOB for NNODES */
490 + * unfortunately we must use a struct sock (most of the fields are useless) as
491 + * this is the standard "agnostic" structure for socket implementation.
492 + * This proofs that it is not "agnostic" enough!
497 + struct ipn_node *node;
501 + * ipn_network network descriptor
503 + * @hnode=hash to find this entry (looking for i-node)
504 + * @unconnectqueue=queue of unconnected (bound) nodes
505 + * @connectqueue=queue of connected nodes (faster for broadcasting)
506 + * @refcnt=reference count (bound or connected sockets)
507 + * @dentry/@mnt=to keep the file system descriptor into memory
508 + * @ipnn_lock=lock for protocol functions
509 + * @protocol=kind of service
510 + * @flags=flags (IPN_FLAG_LOSSLESS)
511 + * @maxports=number of ports available in this network
512 + * @msgpool_nelem=number of pending messages
513 + * @msgpool_size=max number of pending messages *per net* when IPN_FLAG_LOSSLESS
514 + * @msgpool_size=max number of pending messages *per port*when LOSSY
516 + * @send_wait=wait queue waiting for a message in the msgpool (IPN_FLAG_LOSSLESS)
517 + * @msgpool_cache=slab for msgpool (unused yet)
518 + * @proto_private=handle for protocol private data
519 + * @connports=array of connected sockets
521 +struct ipn_network {
522 + struct hlist_node hnode;
523 + struct list_head unconnectqueue;
524 + struct list_head connectqueue;
526 + struct dentry *dentry;
527 + struct vfsmount *mnt;
528 + struct semaphore ipnn_mutex;
530 + struct sockaddr_un sunaddr;
531 + unsigned int protocol;
532 + unsigned int flags;
535 + atomic_t msgpool_nelem;
536 + unsigned short maxports;
537 + unsigned short msgpool_size;
538 + unsigned short mtu;
539 + wait_queue_head_t send_wait;
540 + struct kmem_cache *msgpool_cache;
541 + void *proto_private;
542 + struct ipn_node **connport;
545 +/* struct msgpool_item
546 + * the local copy of the message for dispatching
551 +struct msgpool_item {
554 + unsigned char data[0];
557 +struct msgpool_item *ipn_msgpool_alloc(struct ipn_network *ipnn,int leaky);
558 +void ipn_msgpool_put(struct msgpool_item *old, struct ipn_network *ipnn);
561 + * protocol service:
563 + * @refcnt: number of networks using this protocol
564 + * @newport=upcall for reporting a new port. returns the portno, -1=error
565 + * @handlemsg=dispatch a message.
566 + * should call ipn_proto_sendmsg for each desctination
567 + * can allocate other msgitems using ipn_msgpool_alloc to send
568 + * different messages to different destinations;
569 + * @delport=(may be null) reports the terminatio of a port
570 + * @postnewport,@predelport: similar to newport/delport but during these calls
571 + * the node is (still) connected. Useful when protocols need
572 + * welcome and goodbye messages.
573 + * @ipn_p_setsockopt
574 + * @ipn_p_getsockopt
575 + * @ipn_p_ioctl=(may be null) upcall to manage specific options or ctls.
577 +struct ipn_protocol {
579 + int (*ipn_p_newport)(struct ipn_node *newport);
580 + int (*ipn_p_handlemsg)(struct ipn_node *from,struct msgpool_item *msgitem);
581 + void (*ipn_p_delport)(struct ipn_node *oldport);
582 + void (*ipn_p_postnewport)(struct ipn_node *newport);
583 + void (*ipn_p_predelport)(struct ipn_node *oldport);
584 + int (*ipn_p_newnet)(struct ipn_network *newnet);
585 + int (*ipn_p_resizenet)(struct ipn_network *net,int oldsize,int newsize);
586 + void (*ipn_p_delnet)(struct ipn_network *oldnet);
587 + int (*ipn_p_setsockopt)(struct ipn_node *port,int optname,
588 + char __user *optval, int optlen);
589 + int (*ipn_p_getsockopt)(struct ipn_node *port,int optname,
590 + char __user *optval, int *optlen);
591 + int (*ipn_p_ioctl)(struct ipn_node *port,unsigned int request,
592 + unsigned long arg);
595 +int ipn_proto_register(int protocol,struct ipn_protocol *ipn_service);
596 +int ipn_proto_deregister(int protocol);
598 +int ipn_proto_injectmsg(struct ipn_node *from, struct msgpool_item *msg);
599 +void ipn_proto_sendmsg(struct ipn_node *to, struct msgpool_item *msg);
600 +void ipn_proto_oobsendmsg(struct ipn_node *to, struct msgpool_item *msg);
602 +extern struct sk_buff *(*ipn_handle_frame_hook)(struct ipn_node *p,
603 + struct sk_buff *skb);
606 diff -Naur linux-2.6.28.2/net/Kconfig linux-2.6.28.2-ipn/net/Kconfig
607 --- linux-2.6.28.2/net/Kconfig 2009-01-25 01:42:07.000000000 +0100
608 +++ linux-2.6.28.2-ipn/net/Kconfig 2009-02-01 13:30:06.000000000 +0100
611 source "net/packet/Kconfig"
612 source "net/unix/Kconfig"
613 +source "net/ipn/Kconfig"
614 source "net/xfrm/Kconfig"
615 source "net/iucv/Kconfig"
617 diff -Naur linux-2.6.28.2/net/Makefile linux-2.6.28.2-ipn/net/Makefile
618 --- linux-2.6.28.2/net/Makefile 2009-01-25 01:42:07.000000000 +0100
619 +++ linux-2.6.28.2-ipn/net/Makefile 2009-02-01 13:30:06.000000000 +0100
621 obj-$(CONFIG_INET) += ipv4/
622 obj-$(CONFIG_XFRM) += xfrm/
623 obj-$(CONFIG_UNIX) += unix/
624 +obj-$(CONFIG_IPN) += ipn/
625 ifneq ($(CONFIG_IPV6),)
628 diff -Naur linux-2.6.28.2/net/core/dev.c linux-2.6.28.2-ipn/net/core/dev.c
629 --- linux-2.6.28.2/net/core/dev.c 2009-01-25 01:42:07.000000000 +0100
630 +++ linux-2.6.28.2-ipn/net/core/dev.c 2009-02-01 13:30:07.000000000 +0100
631 @@ -2087,7 +2087,7 @@
633 struct net_device *orig_dev)
635 - if (skb->dev->macvlan_port == NULL)
636 + if (!skb || skb->dev->macvlan_port == NULL)
640 @@ -2100,6 +2100,32 @@
641 #define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb)
644 +#if defined(CONFIG_IPN) || defined(CONFIG_IPN_MODULE)
645 +struct sk_buff *(*ipn_handle_frame_hook)(struct ipn_node *port,
646 + struct sk_buff *skb) __read_mostly;
647 +EXPORT_SYMBOL_GPL(ipn_handle_frame_hook);
649 +static inline struct sk_buff *handle_ipn(struct sk_buff *skb,
650 + struct packet_type **pt_prev,
652 + struct net_device *orig_dev)
654 + struct ipn_node *port;
656 + if (!skb || skb->pkt_type == PACKET_LOOPBACK ||
657 + (port = rcu_dereference(skb->dev->ipn_port)) == NULL)
661 + *ret = deliver_skb(skb, *pt_prev, orig_dev);
664 + return ipn_handle_frame_hook(port, skb);
667 +#define handle_ipn(skb, pt_prev, ret, orig_dev) (skb)
670 #ifdef CONFIG_NET_CLS_ACT
671 /* TODO: Maybe we should just force sch_ingress to be compiled in
672 * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
673 @@ -2278,9 +2304,8 @@
676 skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
679 skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev);
680 + skb = handle_ipn(skb, &pt_prev, &ret, orig_dev);
684 diff -Naur linux-2.6.28.2/net/ipn/Kconfig linux-2.6.28.2-ipn/net/ipn/Kconfig
685 --- linux-2.6.28.2/net/ipn/Kconfig 1970-01-01 01:00:00.000000000 +0100
686 +++ linux-2.6.28.2-ipn/net/ipn/Kconfig 2009-02-01 13:30:09.000000000 +0100
689 +# Unix Domain Sockets
693 + tristate "IPN domain sockets (EXPERIMENTAL)"
694 + depends on EXPERIMENTAL
696 + If you say Y here, you will include support for IPN domain sockets.
697 + Inter Process Networking socket are similar to Unix sockets but
698 + they support peer-to-peer, one-to-many and many-to-many communication
700 + Sub-Modules can be loaded to provide dispatching protocols.
701 + This service include the IPN_BROADCST policy: all the messages get
702 + sent to all the receipients (but the sender itself).
704 + To compile this driver as a module, choose M here: the module will be
707 + If unsure, say 'N'.
709 diff -Naur linux-2.6.28.2/net/ipn/Makefile linux-2.6.28.2-ipn/net/ipn/Makefile
710 --- linux-2.6.28.2/net/ipn/Makefile 1970-01-01 01:00:00.000000000 +0100
711 +++ linux-2.6.28.2-ipn/net/ipn/Makefile 2009-02-01 13:30:09.000000000 +0100
714 +## Makefile for the IPN (Inter Process Networking) domain socket layer.
717 +obj-$(CONFIG_IPN) += ipn.o
719 +ipn-y := af_ipn.o ipn_netdev.o ipn_msgbuf.o
721 diff -Naur linux-2.6.28.2/net/ipn/af_ipn.c linux-2.6.28.2-ipn/net/ipn/af_ipn.c
722 --- linux-2.6.28.2/net/ipn/af_ipn.c 1970-01-01 01:00:00.000000000 +0100
723 +++ linux-2.6.28.2-ipn/net/ipn/af_ipn.c 2009-02-01 13:30:09.000000000 +0100
726 + * Main inter process networking (virtual distributed ethernet) module
727 + * (part of the View-OS project: wiki.virtualsquare.org)
729 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
731 + * This program is free software; you can redistribute it and/or modify
732 + * it under the terms of the GNU General Public License as published by
733 + * the Free Software Foundation; either version 2 of the License, or
734 + * (at your option) any later version.
736 + * Due to this file being licensed under the GPL there is controversy over
737 + * whether this permits you to write a module that #includes this file
738 + * without placing your module under the GPL. Please consult a lawyer for
739 + * advice before doing this.
741 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
745 +#include <linux/init.h>
746 +#include <linux/module.h>
747 +#include <linux/socket.h>
748 +#include <linux/poll.h>
749 +#include <linux/un.h>
750 +#include <linux/list.h>
751 +#include <linux/mount.h>
752 +#include <linux/version.h>
753 +#include <linux/namei.h>
754 +#include <net/sock.h>
755 +#include <net/af_ipn.h>
756 +#include "ipn_netdev.h"
757 +#include "ipn_msgbuf.h"
759 +MODULE_LICENSE("GPL");
760 +MODULE_AUTHOR("VIEW-OS TEAM");
761 +MODULE_DESCRIPTION("IPN Kernel Module");
763 +#define IPN_MAX_PROTO 4
765 +/*extension of RCV_SHUTDOWN defined in include/net/sock.h
766 + * when the bit is set recv fails */
767 +/* NO_OOB: do not send OOB */
768 +#define RCV_SHUTDOWN_NO_OOB 4
769 +/* EXTENDED MASK including OOB */
770 +#define SHUTDOWN_XMASK (SHUTDOWN_MASK | RCV_SHUTDOWN_NO_OOB)
771 +/* if XRCV_SHUTDOWN is all set recv fails */
772 +#define XRCV_SHUTDOWN (RCV_SHUTDOWN | RCV_SHUTDOWN_NO_OOB)
774 +/* Network table and hash */
775 +struct hlist_head ipn_network_table[IPN_HASH_SIZE + 1];
776 +/* not needed. Now protected by ipn_glob_mutex
778 + * DEFINE_SPINLOCK(ipn_table_lock);
780 +static struct kmem_cache *ipn_network_cache;
781 +static struct kmem_cache *ipn_node_cache;
782 +static struct kmem_cache *ipn_msgitem_cache;
783 +static DECLARE_MUTEX(ipn_glob_mutex);
785 +/* Protocol 1: HUB/Broadcast default protocol. Function Prototypes */
786 +static int ipn_bcast_newport(struct ipn_node *newport);
787 +static int ipn_bcast_handlemsg(struct ipn_node *from,
788 + struct msgpool_item *msgitem);
790 +/* default protocol IPN_BROADCAST (0) */
791 +static struct ipn_protocol ipn_bcast = {
793 + .ipn_p_newport=ipn_bcast_newport,
794 + .ipn_p_handlemsg=ipn_bcast_handlemsg};
795 +/* Protocol table */
796 +static struct ipn_protocol *ipn_protocol_table[IPN_MAX_PROTO]={&ipn_bcast};
798 +/* Socket call function prototypes */
799 +static int ipn_release(struct socket *);
800 +static int ipn_bind(struct socket *, struct sockaddr *, int);
801 +static int ipn_connect(struct socket *, struct sockaddr *,
802 + int addr_len, int flags);
803 +static int ipn_getname(struct socket *, struct sockaddr *, int *, int);
804 +static unsigned int ipn_poll(struct file *, struct socket *, poll_table *);
805 +static int ipn_ioctl(struct socket *, unsigned int, unsigned long);
806 +static int ipn_shutdown(struct socket *, int);
807 +static int ipn_sendmsg(struct kiocb *, struct socket *,
808 + struct msghdr *, size_t);
809 +static int ipn_recvmsg(struct kiocb *, struct socket *,
810 + struct msghdr *, size_t, int);
811 +static int ipn_setsockopt(struct socket *sock, int level, int optname,
812 + char __user *optval, int optlen);
813 +static int ipn_getsockopt(struct socket *sock, int level, int optname,
814 + char __user *optval, int __user *optlen);
816 +/* Network table Management
817 + * inode->ipn_network hash table
818 + * LOCKING: MUTEX ipn_glob_mutex must be LOCKED*/
819 +static inline void ipn_insert_network(struct hlist_head *list, struct ipn_network *ipnn)
821 + /* *IPNTL* spin_lock(&ipn_table_lock); */
822 + hlist_add_head(&ipnn->hnode, list);
823 + /* *IPNTL* spin_unlock(&ipn_table_lock); */
826 +static inline void ipn_remove_network(struct ipn_network *ipnn)
828 + /* *IPNTL* spin_lock(&ipn_table_lock); */
829 + hlist_del(&ipnn->hnode);
830 + /* *IPNTL* spin_unlock(&ipn_table_lock); */
833 +static struct ipn_network *ipn_find_network_byinode(struct inode *i)
835 + struct ipn_network *ipnn;
836 + struct hlist_node *node;
838 + /* *IPNTL* spin_lock(&ipn_table_lock);*/
839 + hlist_for_each_entry(ipnn, node,
840 + &ipn_network_table[i->i_ino & (IPN_HASH_SIZE - 1)], hnode) {
841 + struct dentry *dentry = ipnn->dentry;
843 + if(ipnn->refcnt > 0 && dentry && dentry->d_inode == i)
848 + /* *IPNTL* spin_unlock(&ipn_table_lock); */
852 +/* msgpool management
853 + * msgpool_item are ipn_network dependent (each net has its own MTU)
854 + * for each message sent there is one msgpool_item and many struct msgitem
855 + * one for each receipient.
856 + * msgitem are connected to the node's msgqueue or oobmsgqueue.
857 + * when a message is delivered to a process the msgitem is deleted and
858 + * the count of the msgpool_item is decreased.
859 + * msgpool_item elements gets deleted automatically when count is 0*/
862 + struct list_head list;
863 + struct msgpool_item *msg;
866 +/* alloc a fresh msgpool item. count is set to 1.
867 + * the typical use is
868 + * ipn_msgpool_alloc
869 + * for each receipient
870 + * enqueue messages to the process (using msgitem), ipn_msgpool_hold
872 + * The message can be delivered concurrently. init count to 1 guarantees
873 + * that it survives at least until is has been enqueued to all
875 +static struct msgpool_item *_ipn_msgpool_alloc(struct ipn_network *ipnn)
877 + struct msgpool_item *new;
878 + if ((new=kmem_cache_alloc(ipnn->msgpool_cache,GFP_KERNEL)) != NULL) {
879 + atomic_set(&new->count,1);
880 + atomic_inc(&ipnn->msgpool_nelem);
885 +struct msgpool_item *ipn_msgpool_alloc(struct ipn_network *ipnn,int leaky)
887 + if (leaky && (ipnn->flags & IPN_FLAG_LOSSLESS) &&
888 + atomic_read(&ipnn->msgpool_nelem) < ipnn->msgpool_size)
891 + return _ipn_msgpool_alloc(ipnn);
894 +/* If the service il LOSSLESS, this msgpool call waits for an
895 + * available msgpool item */
896 +static struct msgpool_item *ipn_msgpool_alloc_locking(struct ipn_network *ipnn)
898 + if (ipnn->flags & IPN_FLAG_LOSSLESS) {
899 + while (atomic_read(&ipnn->msgpool_nelem) >= ipnn->msgpool_size) {
900 + if (wait_event_interruptible_exclusive(ipnn->send_wait,
901 + atomic_read(&ipnn->msgpool_nelem) < ipnn->msgpool_size))
905 + return _ipn_msgpool_alloc(ipnn);
908 +static inline void ipn_msgpool_hold(struct msgpool_item *msg)
910 + atomic_inc(&msg->count);
913 +/* decrease count and delete msgpool_item if count == 0 */
914 +void ipn_msgpool_put(struct msgpool_item *old,
915 + struct ipn_network *ipnn)
917 + if (atomic_dec_and_test(&old->count)) {
918 + kmem_cache_free(ipnn->msgpool_cache,old);
919 + atomic_dec(&ipnn->msgpool_nelem);
920 + if (ipnn->flags & IPN_FLAG_LOSSLESS) /* this could be done anyway */
921 + wake_up_interruptible(&ipnn->send_wait);
926 +static const struct proto_ops ipn_ops = {
928 + .owner = THIS_MODULE,
929 + .release = ipn_release,
931 + .connect = ipn_connect,
932 + .socketpair = sock_no_socketpair,
933 + .accept = sock_no_accept,
934 + .getname = ipn_getname,
936 + .ioctl = ipn_ioctl,
937 + .listen = sock_no_listen,
938 + .shutdown = ipn_shutdown,
939 + .setsockopt = ipn_setsockopt,
940 + .getsockopt = ipn_getsockopt,
941 + .sendmsg = ipn_sendmsg,
942 + .recvmsg = ipn_recvmsg,
943 + .mmap = sock_no_mmap,
944 + .sendpage = sock_no_sendpage,
947 +static struct proto ipn_proto = {
949 + .owner = THIS_MODULE,
950 + .obj_size = sizeof(struct ipn_sock),
954 + * ipn_node is a separate structure, pointed by ipn_sock -> node
955 + * when a node is "persistent", ipn_node survives while ipn_sock gets released*/
956 +static int ipn_create(struct net *net,struct socket *sock, int protocol)
958 + struct ipn_sock *ipn_sk;
959 + struct ipn_node *ipn_node;
961 + if (net != &init_net)
962 + return -EAFNOSUPPORT;
964 + if (sock->type != SOCK_RAW)
965 + return -EPROTOTYPE;
967 + protocol=protocol-1;
969 + protocol=IPN_BROADCAST-1;
970 + if (protocol < 0 || protocol >= IPN_MAX_PROTO ||
971 + ipn_protocol_table[protocol] == NULL)
972 + return -EPROTONOSUPPORT;
973 + ipn_sk = (struct ipn_sock *) sk_alloc(net, PF_IPN, GFP_KERNEL, &ipn_proto);
977 + ipn_sk->node=ipn_node=kmem_cache_alloc(ipn_node_cache,GFP_KERNEL);
979 + sock_put((struct sock *) ipn_sk);
982 + sock_init_data(sock,(struct sock *) ipn_sk);
983 + sock->state = SS_UNCONNECTED;
984 + sock->ops = &ipn_ops;
985 + sock->sk=(struct sock *)ipn_sk;
986 + INIT_LIST_HEAD(&ipn_node->nodelist);
987 + ipn_node->protocol=protocol;
988 + ipn_node->flags=IPN_NODEFLAG_INUSE;
989 + ipn_node->shutdown=RCV_SHUTDOWN_NO_OOB;
990 + ipn_node->descr[0]=0;
991 + ipn_node->portno=IPN_PORTNO_ANY;
993 + ipn_node->dev=NULL;
994 + ipn_node->proto_private=NULL;
995 + ipn_node->totmsgcount=0;
996 + ipn_node->oobmsgcount=0;
997 + spin_lock_init(&ipn_node->msglock);
998 + INIT_LIST_HEAD(&ipn_node->msgqueue);
999 + INIT_LIST_HEAD(&ipn_node->oobmsgqueue);
1000 + ipn_node->ipn=NULL;
1001 + init_waitqueue_head(&ipn_node->read_wait);
1002 + ipn_node->pbp=NULL;
1006 +/* update # of readers and # of writers counters for an ipn network.
1007 + * This function sends oob messages to nodes requesting the service */
1008 +/* LOCKING ipnn_mutex is locked */
1009 +static void ipn_net_update_counters(struct ipn_network *ipnn,
1010 + int chg_readers, int chg_writers) {
1011 + ipnn->numreaders += chg_readers;
1012 + ipnn->numwriters += chg_writers;
1013 + if (ipnn->mtu >= sizeof(struct numnode_oob))
1015 + struct msgpool_item *ipn_msg=_ipn_msgpool_alloc(ipnn);
1017 + struct numnode_oob *oob_msg=(struct numnode_oob *)(ipn_msg->data);
1018 + struct ipn_node *ipn_node;
1019 + ipn_msg->len=sizeof(struct numnode_oob);
1020 + oob_msg->level=IPN_ANY;
1021 + oob_msg->tag=IPN_OOB_NUMNODE_TAG;
1022 + oob_msg->numreaders=ipnn->numreaders;
1023 + oob_msg->numwriters=ipnn->numwriters;
1024 + list_for_each_entry(ipn_node, &ipnn->connectqueue, nodelist) {
1025 + if (ipn_node->flags & IPN_NODEFLAG_OOB_NUMNODES)
1026 + ipn_proto_oobsendmsg(ipn_node,ipn_msg);
1028 + ipn_msgpool_put(ipn_msg,ipnn);
1033 +/* flush pending messages (for close and shutdown RCV) */
1034 +/* LOCKING: ipnn_mutex is locked */
1035 +static void ipn_flush_recvqueue(struct ipn_node *ipn_node)
1037 + struct ipn_network *ipnn=ipn_node->ipn;
1038 + spin_lock(&ipn_node->msglock);
1039 + while (!list_empty(&ipn_node->msgqueue)) {
1040 + struct msgitem *msgitem=
1041 + list_first_entry(&ipn_node->msgqueue, struct msgitem, list);
1042 + list_del(&msgitem->list);
1043 + ipn_node->totmsgcount--;
1044 + ipn_msgpool_put(msgitem->msg,ipnn);
1045 + kmem_cache_free(ipn_msgitem_cache,msgitem);
1047 + spin_unlock(&ipn_node->msglock);
1050 +/* flush pending oob messages (for socket close) */
1051 +/* LOCKING: ipnn_mutex is locked */
1052 +static void ipn_flush_oobrecvqueue(struct ipn_node *ipn_node)
1054 + struct ipn_network *ipnn=ipn_node->ipn;
1055 + spin_lock(&ipn_node->msglock);
1056 + while (!list_empty(&ipn_node->oobmsgqueue)) {
1057 + struct msgitem *msgitem=
1058 + list_first_entry(&ipn_node->oobmsgqueue, struct msgitem, list);
1059 + list_del(&msgitem->list);
1060 + ipn_node->totmsgcount--;
1061 + ipn_node->oobmsgcount--;
1062 + ipn_msgpool_put(msgitem->msg,ipnn);
1063 + kmem_cache_free(ipn_msgitem_cache,msgitem);
1065 + spin_unlock(&ipn_node->msglock);
1068 +/* Terminate node. The node is "logically" terminated. */
1069 +/* LOCKING: ipn_glob_lock must be locked here */
1070 +static int ipn_terminate_node(struct ipn_node *ipn_node)
1072 + struct ipn_network *ipnn=ipn_node->ipn;
1074 + if (down_interruptible(&ipnn->ipnn_mutex))
1075 + return -ERESTARTSYS;
1076 + if (ipn_node->portno >= 0) {
1077 + ipn_protocol_table[ipnn->protocol]->ipn_p_predelport(ipn_node);
1078 + ipnn->connport[ipn_node->portno]=NULL;
1080 + list_del(&ipn_node->nodelist);
1081 + ipn_flush_recvqueue(ipn_node);
1082 + ipn_flush_oobrecvqueue(ipn_node);
1083 + if (ipn_node->portno >= 0)
1084 + ipn_protocol_table[ipnn->protocol]->ipn_p_delport(ipn_node);
1085 + ipn_node->ipn=NULL;
1086 + ipn_net_update_counters(ipnn,
1087 + (ipn_node->shutdown & RCV_SHUTDOWN)?0:-1,
1088 + (ipn_node->shutdown & SEND_SHUTDOWN)?0:-1);
1089 + ipn_node->shutdown = SHUTDOWN_XMASK;
1090 + up(&ipnn->ipnn_mutex);
1091 + if (ipn_node->dev)
1092 + ipn_netdev_close(ipn_node);
1093 + /* No more network elements */
1095 + if (ipnn->refcnt == 0)
1097 + ipn_protocol_table[ipnn->protocol]->ipn_p_delnet(ipnn);
1098 + ipn_remove_network(ipnn);
1099 + ipn_protocol_table[ipnn->protocol]->refcnt--;
1100 + if (ipnn->dentry) {
1101 + dput(ipnn->dentry);
1102 + mntput(ipnn->mnt);
1104 + if (ipnn->msgpool_cache)
1105 + ipn_msgbuf_put(ipnn->msgpool_cache);
1106 + if (ipnn->connport)
1107 + kfree(ipnn->connport);
1108 + kmem_cache_free(ipn_network_cache, ipnn);
1109 + module_put(THIS_MODULE);
1112 + if (ipn_node->pbp) {
1113 + kfree(ipn_node->pbp);
1114 + ipn_node->pbp=NULL;
1119 +/* release of a socket */
1120 +static int ipn_release (struct socket *sock)
1122 + struct ipn_sock *ipn_sk=(struct ipn_sock *)sock->sk;
1123 + struct ipn_node *ipn_node=ipn_sk->node;
1125 + if (down_interruptible(&ipn_glob_mutex))
1126 + return -ERESTARTSYS;
1127 + if (ipn_node->flags & IPN_NODEFLAG_PERSIST) {
1128 + ipn_node->flags &= ~IPN_NODEFLAG_INUSE;
1130 + up(&ipn_glob_mutex);
1132 + rv=ipn_terminate_node(ipn_node);
1133 + up(&ipn_glob_mutex);
1136 + kmem_cache_free(ipn_node_cache,ipn_node);
1140 + sock_put((struct sock *) ipn_sk);
1144 +/* _set persist, change the persistence of a node,
1145 + * when persistence gets cleared and the node is no longer used
1146 + * the node is terminated and freed.
1147 + * ipn_glob_mutex must be locked */
1148 +static int _ipn_setpersist(struct ipn_node *ipn_node, int persist)
1152 + ipn_node->flags |= IPN_NODEFLAG_PERSIST;
1154 + ipn_node->flags &= ~IPN_NODEFLAG_PERSIST;
1155 + if (!(ipn_node->flags & IPN_NODEFLAG_INUSE)) {
1156 + rv=ipn_terminate_node(ipn_node);
1158 + kmem_cache_free(ipn_node_cache,ipn_node);
1165 + * lock ipn_glob_mutex and call __ipn_setpersist above */
1166 +static int ipn_setpersist(struct ipn_node *ipn_node, int persist)
1169 + if (ipn_node->dev == NULL)
1171 + if (down_interruptible(&ipn_glob_mutex))
1172 + return -ERESTARTSYS;
1173 + rv=_ipn_setpersist(ipn_node,persist);
1174 + up(&ipn_glob_mutex);
1178 +/* several network parameters can be set by setsockopt prior to bind */
1179 +/* struct pre_bind_parms is a temporary stucture connected to ipn_node->pbp
1180 + * to keep the parameter values. */
1181 +struct pre_bind_parms {
1182 + unsigned short maxports;
1183 + unsigned short flags;
1184 + unsigned short msgpoolsize;
1185 + unsigned short mtu;
1186 + unsigned short mode;
1189 +/* STD_PARMS: BITS_PER_LONG nodes, no flags, BITS_PER_BYTE pending msgs,
1190 + * Ethernet + VLAN MTU*/
1191 +#define STD_BIND_PARMS {BITS_PER_LONG, 0, BITS_PER_BYTE, 1514, 0x777};
1193 +static int ipn_mkname(struct sockaddr_un * sunaddr, int len)
1195 + if (len <= sizeof(short) || len > sizeof(*sunaddr))
1197 + if (!sunaddr || sunaddr->sun_family != AF_IPN)
1200 + * This may look like an off by one error but it is a bit more
1201 + * subtle. 108 is the longest valid AF_IPN path for a binding.
1202 + * sun_path[108] doesnt as such exist. However in kernel space
1203 + * we are guaranteed that it is a valid memory location in our
1204 + * kernel address buffer.
1206 + ((char *)sunaddr)[len]=0;
1207 + len = strlen(sunaddr->sun_path)+1+sizeof(short);
1212 +static int ipn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
1214 + struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
1215 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1216 + struct nameidata nd;
1217 + struct ipn_network *ipnn;
1218 + struct dentry * dentry = NULL;
1220 + struct pre_bind_parms parms=STD_BIND_PARMS;
1222 + //printk("IPN bind\n");
1224 + if (down_interruptible(&ipn_glob_mutex))
1225 + return -ERESTARTSYS;
1226 + if (sock->state != SS_UNCONNECTED ||
1227 + ipn_node->ipn != NULL) {
1232 + if (ipn_node->protocol >= 0 &&
1233 + (ipn_node->protocol >= IPN_MAX_PROTO ||
1234 + ipn_protocol_table[ipn_node->protocol] == NULL)) {
1235 + err= -EPROTONOSUPPORT;
1239 + addr_len = ipn_mkname(sunaddr, addr_len);
1240 + if (addr_len < 0) {
1245 + /* check if there is already an ipn-network socket with that name */
1246 + err = path_lookup(sunaddr->sun_path, LOOKUP_FOLLOW, &nd);
1247 + if (err) { /* it does not exist, NEW IPN socket! */
1248 + unsigned int mode;
1249 + /* Is it everything okay with the parent? */
1250 + err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd);
1252 + goto out_mknod_parent;
1253 + /* Do I have the permission to create a file? */
1254 + dentry = lookup_create(&nd, 0);
1255 + err = PTR_ERR(dentry);
1256 + if (IS_ERR(dentry))
1257 + goto out_mknod_unlock;
1259 + * All right, let's create it.
1261 + if (ipn_node->pbp)
1262 + mode = ipn_node->pbp->mode;
1264 + mode = SOCK_INODE(sock)->i_mode;
1265 + mode = S_IFSOCK | (mode & ~current->fs->umask);
1266 + err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
1268 + goto out_mknod_dput;
1269 + mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
1270 + dput(nd.path.dentry);
1271 + nd.path.dentry = dentry;
1272 + /* create a new ipn_network item */
1273 + if (ipn_node->pbp)
1274 + parms=*ipn_node->pbp;
1275 + ipnn=kmem_cache_zalloc(ipn_network_cache,GFP_KERNEL);
1278 + goto out_mknod_dput_ipnn;
1280 + ipnn->connport=kzalloc(parms.maxports * sizeof(struct ipn_node *),GFP_KERNEL);
1281 + if (!ipnn->connport) {
1283 + goto out_mknod_dput_ipnn2;
1286 + /* module refcnt is incremented for each network, thus
1287 + * rmmod is forbidden if there are persistent node */
1288 + if (!try_module_get(THIS_MODULE)) {
1290 + goto out_mknod_dput_ipnn2;
1292 + memcpy(&ipnn->sunaddr,sunaddr,addr_len);
1293 + ipnn->mtu=parms.mtu;
1294 + ipnn->msgpool_cache=ipn_msgbuf_get(ipnn->mtu);
1295 + if (!ipnn->msgpool_cache) {
1297 + goto out_mknod_dput_putmodule;
1299 + INIT_LIST_HEAD(&ipnn->unconnectqueue);
1300 + INIT_LIST_HEAD(&ipnn->connectqueue);
1302 + ipnn->dentry=nd.path.dentry;
1303 + ipnn->mnt=nd.path.mnt;
1304 + init_MUTEX(&ipnn->ipnn_mutex);
1305 + ipnn->sunaddr_len=addr_len;
1306 + ipnn->protocol=ipn_node->protocol;
1307 + if (ipnn->protocol < 0) ipnn->protocol = 0;
1308 + ipn_protocol_table[ipnn->protocol]->refcnt++;
1309 + ipnn->flags=parms.flags;
1310 + ipnn->numreaders=0;
1311 + ipnn->numwriters=0;
1312 + ipnn->maxports=parms.maxports;
1313 + atomic_set(&ipnn->msgpool_nelem,0);
1314 + ipnn->msgpool_size=parms.msgpoolsize;
1315 + ipnn->proto_private=NULL;
1316 + init_waitqueue_head(&ipnn->send_wait);
1317 + err=ipn_protocol_table[ipnn->protocol]->ipn_p_newnet(ipnn);
1319 + goto out_mknod_dput_putmodule;
1320 + ipn_insert_network(&ipn_network_table[nd.path.dentry->d_inode->i_ino & (IPN_HASH_SIZE-1)],ipnn);
1322 + /* join an existing network */
1323 + if (parms.flags & IPN_FLAG_EXCL) {
1327 + err = vfs_permission(&nd, MAY_EXEC);
1330 + err = -ECONNREFUSED;
1331 + if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode))
1333 + ipnn=ipn_find_network_byinode(nd.path.dentry->d_inode);
1334 + if (!ipnn || (ipnn->flags & IPN_FLAG_TERMINATED) ||
1335 + (ipnn->flags & IPN_FLAG_EXCL))
1337 + list_add_tail(&ipn_node->nodelist,&ipnn->unconnectqueue);
1340 + if (ipn_node->pbp) {
1341 + kfree(ipn_node->pbp);
1342 + ipn_node->pbp=NULL;
1344 + ipn_node->ipn=ipnn;
1345 + ipn_node->flags |= IPN_NODEFLAG_BOUND;
1346 + up(&ipn_glob_mutex);
1350 + path_put(&nd.path);
1352 + up(&ipn_glob_mutex);
1355 +out_mknod_dput_putmodule:
1356 + module_put(THIS_MODULE);
1357 +out_mknod_dput_ipnn2:
1358 + kfree(ipnn->connport);
1359 +out_mknod_dput_ipnn:
1360 + kmem_cache_free(ipn_network_cache,ipnn);
1364 + mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
1365 + path_put(&nd.path);
1369 + up(&ipn_glob_mutex);
1374 +static int ipn_connect(struct socket *sock, struct sockaddr *addr,
1375 + int addr_len, int flags){
1376 + struct sockaddr_un *sunaddr=(struct sockaddr_un*)addr;
1377 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1378 + struct nameidata nd;
1379 + struct ipn_network *ipnn,*previousipnn;
1383 + /* the socket cannot be connected twice */
1384 + if (sock->state != SS_UNCONNECTED)
1387 + if (down_interruptible(&ipn_glob_mutex))
1388 + return -ERESTARTSYS;
1390 + if ((previousipnn=ipn_node->ipn) == NULL) { /* unbound */
1391 + unsigned char mustshutdown=0;
1392 + err = ipn_mkname(sunaddr, addr_len);
1396 + err = path_lookup(sunaddr->sun_path, LOOKUP_FOLLOW, &nd);
1399 + err = vfs_permission(&nd, MAY_READ);
1401 + if (err == -EACCES || err == -EROFS)
1402 + mustshutdown|=RCV_SHUTDOWN;
1406 + err = vfs_permission(&nd, MAY_WRITE);
1408 + if (err == -EACCES)
1409 + mustshutdown|=SEND_SHUTDOWN;
1413 + mustshutdown |= ipn_node->shutdown;
1414 + /* if the combination of shutdown and permissions leaves
1415 + * no abilities, connect returns EACCES */
1416 + if (mustshutdown == SHUTDOWN_XMASK) {
1421 + ipn_node->shutdown=mustshutdown;
1423 + if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode)) {
1424 + err = -ECONNREFUSED;
1427 + ipnn=ipn_find_network_byinode(nd.path.dentry->d_inode);
1428 + if (!ipnn || (ipnn->flags & IPN_FLAG_TERMINATED)) {
1429 + err = -ECONNREFUSED;
1432 + if (ipn_node->protocol == IPN_ANY)
1433 + ipn_node->protocol=ipnn->protocol;
1434 + else if (ipnn->protocol != ipn_node->protocol) {
1438 + path_put(&nd.path);
1439 + ipn_node->ipn=ipnn;
1441 + ipnn=ipn_node->ipn;
1443 + if (down_interruptible(&ipnn->ipnn_mutex)) {
1447 + portno = ipn_protocol_table[ipnn->protocol]->ipn_p_newport(ipn_node);
1448 + if (portno >= 0 && portno<ipnn->maxports) {
1449 + sock->state = SS_CONNECTED;
1450 + ipn_node->portno=portno;
1451 + ipnn->connport[portno]=ipn_node;
1452 + if (!(ipn_node->flags & IPN_NODEFLAG_BOUND)) {
1454 + list_del(&ipn_node->nodelist);
1456 + list_add_tail(&ipn_node->nodelist,&ipnn->connectqueue);
1457 + ipn_net_update_counters(ipnn,
1458 + (ipn_node->shutdown & RCV_SHUTDOWN)?0:1,
1459 + (ipn_node->shutdown & SEND_SHUTDOWN)?0:1);
1461 + ipn_node->ipn=previousipnn; /* undo changes on ipn_node->ipn */
1462 + err=-EADDRNOTAVAIL;
1464 + up(&ipnn->ipnn_mutex);
1465 + up(&ipn_glob_mutex);
1469 + path_put(&nd.path);
1471 + up(&ipn_glob_mutex);
1475 +static int ipn_getname(struct socket *sock, struct sockaddr *uaddr,
1476 + int *uaddr_len, int peer) {
1477 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1478 + struct ipn_network *ipnn=ipn_node->ipn;
1479 + struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
1482 + if (down_interruptible(&ipn_glob_mutex))
1483 + return -ERESTARTSYS;
1485 + *uaddr_len = ipnn->sunaddr_len;
1486 + memcpy(sunaddr,&ipnn->sunaddr,*uaddr_len);
1489 + up(&ipn_glob_mutex);
1494 +static unsigned int ipn_poll(struct file *file, struct socket *sock,
1495 + poll_table *wait) {
1496 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1497 + struct ipn_network *ipnn=ipn_node->ipn;
1498 + unsigned int mask=0;
1501 + poll_wait(file,&ipn_node->read_wait,wait);
1502 + if (ipnn->flags & IPN_FLAG_LOSSLESS)
1503 + poll_wait(file,&ipnn->send_wait,wait);
1504 + /* POLLIN if recv succeeds,
1505 + * POLL{PRI,RDNORM} if there are {oob,non-oob} messages */
1506 + if (ipn_node->totmsgcount > 0) mask |= POLLIN;
1507 + if (!(list_empty(&ipn_node->msgqueue))) mask |= POLLRDNORM;
1508 + if (!(list_empty(&ipn_node->oobmsgqueue))) mask |= POLLPRI;
1509 + if ((!(ipnn->flags & IPN_FLAG_LOSSLESS)) |
1510 + (atomic_read(&ipnn->msgpool_nelem) < ipnn->msgpool_size))
1511 + mask |= POLLOUT | POLLWRNORM;
1516 +/* connect netdev (from ioctl). connect a bound socket to a
1517 + * network device TAP or GRAB */
1518 +static int ipn_connect_netdev(struct socket *sock,struct ifreq *ifr)
1521 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1522 + struct ipn_network *ipnn=ipn_node->ipn;
1523 + if (!capable(CAP_NET_ADMIN))
1525 + if (sock->state != SS_UNCONNECTED)
1528 + return -ENOTCONN; /* Maybe we need a different error for "NOT BOUND" */
1529 + if (down_interruptible(&ipn_glob_mutex))
1530 + return -ERESTARTSYS;
1531 + if (down_interruptible(&ipnn->ipnn_mutex)) {
1532 + up(&ipn_glob_mutex);
1533 + return -ERESTARTSYS;
1535 + ipn_node->dev=ipn_netdev_alloc(ipn_node->net,ifr->ifr_flags,ifr->ifr_name,&err);
1536 + if (ipn_node->dev) {
1538 + portno = ipn_protocol_table[ipnn->protocol]->ipn_p_newport(ipn_node);
1539 + if (portno >= 0 && portno<ipnn->maxports) {
1540 + sock->state = SS_CONNECTED;
1541 + ipn_node->portno=portno;
1542 + ipn_node->flags |= ifr->ifr_flags & IPN_NODEFLAG_DEVMASK;
1543 + ipnn->connport[portno]=ipn_node;
1544 + err=ipn_netdev_activate(ipn_node);
1546 + sock->state = SS_UNCONNECTED;
1547 + ipn_protocol_table[ipnn->protocol]->ipn_p_delport(ipn_node);
1548 + ipn_node->dev=NULL;
1549 + ipn_node->portno= -1;
1550 + ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
1551 + ipnn->connport[portno]=NULL;
1553 + ipn_protocol_table[ipnn->protocol]->ipn_p_postnewport(ipn_node);
1554 + list_del(&ipn_node->nodelist);
1555 + list_add_tail(&ipn_node->nodelist,&ipnn->connectqueue);
1558 + ipn_netdev_close(ipn_node);
1559 + err=-EADDRNOTAVAIL;
1560 + ipn_node->dev=NULL;
1564 + up(&ipnn->ipnn_mutex);
1565 + up(&ipn_glob_mutex);
1569 +/* join a netdev, a socket gets connected to a persistent node
1570 + * not connected to another socket */
1571 +static int ipn_join_netdev(struct socket *sock,struct ifreq *ifr)
1574 + struct net_device *dev;
1575 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1576 + struct ipn_node *ipn_joined;
1577 + struct ipn_network *ipnn=ipn_node->ipn;
1578 + if (sock->state != SS_UNCONNECTED)
1580 + if (down_interruptible(&ipn_glob_mutex))
1581 + return -ERESTARTSYS;
1582 + if (down_interruptible(&ipnn->ipnn_mutex)) {
1583 + up(&ipn_glob_mutex);
1584 + return -ERESTARTSYS;
1586 + dev=__dev_get_by_name(ipn_node->net,ifr->ifr_name);
1588 + dev=__dev_get_by_index(ipn_node->net,ifr->ifr_ifindex);
1589 + if (dev && (ipn_joined=ipn_netdev2node(dev)) != NULL) { /* the interface does exist */
1591 + for (i=0;i<ipnn->maxports && ipn_joined != ipnn->connport[i] ;i++)
1593 + if (i < ipnn->maxports) { /* found */
1594 + /* ipn_joined is substituted to ipn_node */
1595 + ((struct ipn_sock *)sock->sk)->node=ipn_joined;
1596 + ipn_joined->flags |= IPN_NODEFLAG_INUSE;
1598 + kmem_cache_free(ipn_node_cache,ipn_node);
1602 + err=-EADDRNOTAVAIL;
1603 + up(&ipnn->ipnn_mutex);
1604 + up(&ipn_glob_mutex);
1608 +/* set persistence of a node looking for it by interface name
1609 + * (it is for sysadm, to close network interfaces)*/
1610 +static int ipn_setpersist_netdev(struct ifreq *ifr, int value)
1612 + struct net_device *dev;
1613 + struct ipn_node *ipn_node;
1615 + if (!capable(CAP_NET_ADMIN))
1617 + if (down_interruptible(&ipn_glob_mutex))
1618 + return -ERESTARTSYS;
1619 + dev=__dev_get_by_name(&init_net,ifr->ifr_name);
1621 + dev=__dev_get_by_index(&init_net,ifr->ifr_ifindex);
1622 + if (dev && (ipn_node=ipn_netdev2node(dev)) != NULL)
1623 + _ipn_setpersist(ipn_node,value);
1625 + err=-EADDRNOTAVAIL;
1626 + up(&ipn_glob_mutex);
1631 +static int ipn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) {
1632 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1633 + struct ipn_network *ipnn=ipn_node->ipn;
1634 + void __user* argp = (void __user*)arg;
1637 + if (ipn_node->shutdown == SHUTDOWN_XMASK)
1638 + return -ECONNRESET;
1640 + /* get arguments */
1644 + case IPN_SETPERSIST_NETDEV:
1645 + case IPN_CLRPERSIST_NETDEV:
1646 + case IPN_CONN_NETDEV:
1647 + case IPN_JOIN_NETDEV:
1648 + case SIOCSIFHWADDR:
1649 + if (copy_from_user(&ifr, argp, sizeof ifr))
1651 + ifr.ifr_name[IFNAMSIZ-1] = '\0';
1654 + /* actions for unconnected and unbound sockets */
1656 + case IPN_SETPERSIST_NETDEV:
1657 + return ipn_setpersist_netdev(&ifr,1);
1658 + case IPN_CLRPERSIST_NETDEV:
1659 + return ipn_setpersist_netdev(&ifr,0);
1660 + case SIOCSIFHWADDR:
1661 + if (capable(CAP_NET_ADMIN))
1663 + if (ipn_node->dev && (ipn_node->flags &IPN_NODEFLAG_TAP))
1664 + return dev_set_mac_address(ipn_node->dev, &ifr.ifr_hwaddr);
1666 + return -EADDRNOTAVAIL;
1668 + if (ipnn == NULL || (ipnn->flags & IPN_FLAG_TERMINATED))
1670 + /* actions for connected or bound sockets */
1672 + case IPN_CONN_NETDEV:
1673 + return ipn_connect_netdev(sock,&ifr);
1674 + case IPN_JOIN_NETDEV:
1675 + return ipn_join_netdev(sock,&ifr);
1676 + case IPN_SETPERSIST:
1677 + return ipn_setpersist(ipn_node,arg);
1681 + if (down_interruptible(&ipnn->ipnn_mutex))
1682 + return -ERESTARTSYS;
1683 + rv=ipn_protocol_table[ipn_node->protocol]->ipn_p_ioctl(ipn_node,cmd,arg);
1684 + up(&ipnn->ipnn_mutex);
1687 + return -EOPNOTSUPP;
1691 +/* shutdown: close socket for input or for output.
1692 + * shutdown can be called prior to connect and it is not reversible */
1693 +static int ipn_shutdown(struct socket *sock, int mode) {
1694 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1695 + struct ipn_network *ipnn=ipn_node->ipn;
1696 + int oldshutdown=ipn_node->shutdown;
1697 + mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
1699 + ipn_node->shutdown |= mode;
1702 + if (down_interruptible(&ipnn->ipnn_mutex)) {
1703 + ipn_node->shutdown = oldshutdown;
1704 + return -ERESTARTSYS;
1706 + oldshutdown=ipn_node->shutdown-oldshutdown;
1707 + if (sock->state == SS_CONNECTED && oldshutdown) {
1708 + ipn_net_update_counters(ipnn,
1709 + (ipn_node->shutdown & RCV_SHUTDOWN)?0:-1,
1710 + (ipn_node->shutdown & SEND_SHUTDOWN)?0:-1);
1713 + /* if recv channel has been shut down, flush the recv queue */
1714 + if ((ipn_node->shutdown & RCV_SHUTDOWN))
1715 + ipn_flush_recvqueue(ipn_node);
1716 + up(&ipnn->ipnn_mutex);
1721 +/* injectmsg: a new message is entering the ipn network.
1722 + * injectmsg gets called by send and by the grab/tap node */
1723 +int ipn_proto_injectmsg(struct ipn_node *from, struct msgpool_item *msg)
1725 + struct ipn_network *ipnn=from->ipn;
1727 + if (down_interruptible(&ipnn->ipnn_mutex))
1730 + ipn_protocol_table[ipnn->protocol]->ipn_p_handlemsg(from, msg);
1731 + up(&ipnn->ipnn_mutex);
1737 +static int ipn_sendmsg(struct kiocb *kiocb, struct socket *sock,
1738 + struct msghdr *msg, size_t len) {
1739 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1740 + struct ipn_network *ipnn=ipn_node->ipn;
1741 + struct msgpool_item *newmsg;
1744 + if (unlikely(sock->state != SS_CONNECTED))
1746 + if (unlikely(ipn_node->shutdown & SEND_SHUTDOWN)) {
1747 + if (ipn_node->shutdown == SHUTDOWN_XMASK)
1748 + return -ECONNRESET;
1752 + if (len > ipnn->mtu)
1753 + return -EOVERFLOW;
1754 + newmsg=ipn_msgpool_alloc_locking(ipnn);
1758 + err=memcpy_fromiovec(newmsg->data, msg->msg_iov, len);
1760 + ipn_proto_injectmsg(ipn_node, newmsg);
1761 + ipn_msgpool_put(newmsg,ipnn);
1765 +/* enqueue an oob message. "to" is the destination */
1766 +void ipn_proto_oobsendmsg(struct ipn_node *to, struct msgpool_item *msg)
1769 + if (!to->dev) { /* no oob to netdev */
1770 + struct msgitem *msgitem;
1771 + struct ipn_network *ipnn=to->ipn;
1772 + spin_lock(&to->msglock);
1773 + if ((to->shutdown & RCV_SHUTDOWN_NO_OOB) == 0 &&
1774 + (ipnn->flags & IPN_FLAG_LOSSLESS ||
1775 + to->oobmsgcount < ipnn->msgpool_size)) {
1776 + if ((msgitem=kmem_cache_alloc(ipn_msgitem_cache,GFP_KERNEL))!=NULL) {
1778 + to->totmsgcount++;
1779 + to->oobmsgcount++;
1780 + list_add_tail(&msgitem->list, &to->oobmsgqueue);
1781 + ipn_msgpool_hold(msg);
1784 + spin_unlock(&to->msglock);
1785 + wake_up_interruptible(&to->read_wait);
1790 +/* ipn_proto_sendmsg is called by protocol implementation to enqueue a
1791 + * for a destination (to).*/
1792 +void ipn_proto_sendmsg(struct ipn_node *to, struct msgpool_item *msg)
1796 + ipn_netdev_sendmsg(to,msg);
1799 + struct msgitem *msgitem;
1800 + struct ipn_network *ipnn=to->ipn;
1801 + spin_lock(&to->msglock);
1802 + if (likely((to->shutdown & RCV_SHUTDOWN)==0)) {
1803 + /*if (unlikely((ipnn->flags & IPN_FLAG_LOSSLESS) == 0 ||
1804 + to->totmsgcount >= ipnn->msgpool_size))
1806 + if (likely(ipnn->flags & IPN_FLAG_LOSSLESS ||
1807 + to->totmsgcount < ipnn->msgpool_size)) {
1808 + if ((msgitem=kmem_cache_alloc(ipn_msgitem_cache,GFP_KERNEL))!=NULL) {
1810 + to->totmsgcount++;
1811 + list_add_tail(&msgitem->list, &to->msgqueue);
1812 + ipn_msgpool_hold(msg);
1816 + spin_unlock(&to->msglock);
1817 + wake_up_interruptible(&to->read_wait);
1823 +static int ipn_recvmsg(struct kiocb *kiocb, struct socket *sock,
1824 + struct msghdr *msg, size_t len, int flags) {
1825 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1826 + struct ipn_network *ipnn=ipn_node->ipn;
1827 + struct msgitem *msgitem;
1828 + struct msgpool_item *currmsg;
1830 + if (unlikely(sock->state != SS_CONNECTED))
1833 + if (unlikely((ipn_node->shutdown & XRCV_SHUTDOWN) == XRCV_SHUTDOWN)) {
1834 + if (ipn_node->shutdown == SHUTDOWN_XMASK) /*EOF, nothing can be read*/
1837 + return -EPIPE; /*trying to read on a write only node */
1840 + /* wait for a message */
1841 + spin_lock(&ipn_node->msglock);
1842 + while (ipn_node->totmsgcount == 0) {
1843 + spin_unlock(&ipn_node->msglock);
1844 + if (wait_event_interruptible(ipn_node->read_wait,
1845 + !(ipn_node->totmsgcount == 0)))
1846 + return -ERESTARTSYS;
1847 + spin_lock(&ipn_node->msglock);
1849 + /* oob gets delivered first. oob are rare */
1850 + if (likely(list_empty(&ipn_node->oobmsgqueue)))
1851 + msgitem=list_first_entry(&ipn_node->msgqueue, struct msgitem, list);
1853 + msgitem=list_first_entry(&ipn_node->oobmsgqueue, struct msgitem, list);
1854 + msg->msg_flags |= MSG_OOB;
1855 + ipn_node->oobmsgcount--;
1857 + list_del(&msgitem->list);
1858 + ipn_node->totmsgcount--;
1859 + spin_unlock(&ipn_node->msglock);
1860 + currmsg=msgitem->msg;
1861 + if (currmsg->len < len)
1863 + memcpy_toiovec(msg->msg_iov, currmsg->data, len);
1864 + ipn_msgpool_put(currmsg,ipnn);
1865 + kmem_cache_free(ipn_msgitem_cache,msgitem);
1870 +/* resize a network: change the # of communication ports (connport) */
1871 +static int ipn_netresize(struct ipn_network *ipnn,int newsize)
1874 + struct ipn_node **newconnport;
1875 + struct ipn_node **oldconnport;
1877 + if (down_interruptible(&ipnn->ipnn_mutex))
1878 + return -ERESTARTSYS;
1879 + oldsize=ipnn->maxports;
1880 + if (newsize == oldsize) {
1881 + up(&ipnn->ipnn_mutex);
1885 + /* shrink a network. all the ports we are going to eliminate
1886 + * must be unused! */
1887 + if (newsize < oldsize) {
1889 + for (i=newsize; i<oldsize; i++)
1890 + if (ipnn->connport[i]) {
1891 + up(&ipnn->ipnn_mutex);
1892 + return -EADDRINUSE;
1896 + oldconnport=ipnn->connport;
1897 + /* allocate the new connport array and copy the old one */
1898 + newconnport=kzalloc(newsize * sizeof(struct ipn_node *),GFP_KERNEL);
1899 + if (!newconnport) {
1900 + up(&ipnn->ipnn_mutex);
1903 + memcpy(newconnport,oldconnport,min * sizeof(struct ipn_node *));
1904 + ipnn->connport=newconnport;
1905 + ipnn->maxports=newsize;
1906 + /* notify the protocol that the netowrk has been resized */
1907 + err=ipn_protocol_table[ipnn->protocol]->ipn_p_resizenet(ipnn,oldsize,newsize);
1909 + /* roll back if the resize operation failed for the protocol */
1910 + ipnn->connport=oldconnport;
1911 + ipnn->maxports=oldsize;
1912 + kfree(newconnport);
1914 + /* successful mission, network resized */
1915 + kfree(oldconnport);
1916 + up(&ipnn->ipnn_mutex);
1920 +/* IPN SETSOCKOPT */
1921 +static int ipn_setsockopt(struct socket *sock, int level, int optname,
1922 + char __user *optval, int optlen) {
1923 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
1924 + struct ipn_network *ipnn=ipn_node->ipn;
1926 + if (ipn_node->shutdown == SHUTDOWN_XMASK)
1927 + return -ECONNRESET;
1928 + if (level != 0 && level != ipn_node->protocol+1)
1929 + return -EPROTONOSUPPORT;
1931 + /* protocol specific sockopt */
1934 + if (down_interruptible(&ipnn->ipnn_mutex))
1935 + return -ERESTARTSYS;
1936 + rv=ipn_protocol_table[ipn_node->protocol]->ipn_p_setsockopt(ipn_node,optname,optval,optlen);
1937 + up(&ipnn->ipnn_mutex);
1940 + return -EOPNOTSUPP;
1942 + if (optname == IPN_SO_DESCR) {
1943 + if (optlen > IPN_DESCRLEN)
1946 + memset(ipn_node->descr,0,IPN_DESCRLEN);
1947 + if (copy_from_user(ipn_node->descr,optval,optlen))
1948 + ipn_node->descr[0]=0;
1950 + ipn_node->descr[optlen-1]=0;
1954 + if (optlen < sizeof(int))
1956 + else if ((optname & IPN_SO_PREBIND) && (ipnn != NULL))
1960 + get_user(val, (int __user *) optval);
1961 + if ((optname & IPN_SO_PREBIND) && !ipn_node->pbp) {
1962 + struct pre_bind_parms std=STD_BIND_PARMS;
1963 + ipn_node->pbp=kzalloc(sizeof(struct pre_bind_parms),GFP_KERNEL);
1964 + if (!ipn_node->pbp)
1966 + *(ipn_node->pbp)=std;
1968 + switch (optname) {
1970 + if (sock->state == SS_UNCONNECTED)
1971 + ipn_node->portno=val;
1975 + case IPN_SO_CHANGE_NUMNODES:
1976 + if ((ipn_node->flags & IPN_NODEFLAG_BOUND)!=0) {
1980 + return ipn_netresize(ipnn,val);
1984 + case IPN_SO_WANT_OOB_NUMNODES:
1986 + ipn_node->flags |= IPN_NODEFLAG_OOB_NUMNODES;
1988 + ipn_node->flags &= ~IPN_NODEFLAG_OOB_NUMNODES;
1990 + case IPN_SO_HANDLE_OOB:
1992 + ipn_node->shutdown &= ~RCV_SHUTDOWN_NO_OOB;
1994 + ipn_node->shutdown |= RCV_SHUTDOWN_NO_OOB;
2000 + ipn_node->pbp->mtu=val;
2002 + case IPN_SO_NUMNODES:
2006 + ipn_node->pbp->maxports=val;
2008 + case IPN_SO_MSGPOOLSIZE:
2012 + ipn_node->pbp->msgpoolsize=val;
2014 + case IPN_SO_FLAGS:
2015 + ipn_node->pbp->flags=val;
2018 + ipn_node->pbp->mode=val;
2027 +/* IPN GETSOCKOPT */
2028 +static int ipn_getsockopt(struct socket *sock, int level, int optname,
2029 + char __user *optval, int __user *optlen) {
2030 + struct ipn_node *ipn_node=((struct ipn_sock *)sock->sk)->node;
2031 + struct ipn_network *ipnn=ipn_node->ipn;
2034 + if (ipn_node->shutdown == SHUTDOWN_XMASK)
2035 + return -ECONNRESET;
2036 + if (level != 0 && level != ipn_node->protocol+1)
2037 + return -EPROTONOSUPPORT;
2041 + /* protocol specific sockopt */
2042 + if (down_interruptible(&ipnn->ipnn_mutex))
2043 + return -ERESTARTSYS;
2044 + rv=ipn_protocol_table[ipn_node->protocol]->ipn_p_getsockopt(ipn_node,optname,optval,optlen);
2045 + up(&ipnn->ipnn_mutex);
2048 + return -EOPNOTSUPP;
2050 + if (get_user(len, optlen))
2052 + if (optname == IPN_SO_DESCR) {
2053 + if (len < IPN_DESCRLEN)
2056 + if (len > IPN_DESCRLEN)
2058 + if(put_user(len, optlen))
2060 + if(copy_to_user(optval,ipn_node->descr,len))
2066 + switch (optname) {
2068 + val=ipn_node->portno;
2073 + else if (ipn_node->pbp)
2074 + val=ipn_node->pbp->mtu;
2076 + case IPN_SO_NUMNODES:
2078 + val=ipnn->maxports;
2079 + else if (ipn_node->pbp)
2080 + val=ipn_node->pbp->maxports;
2082 + case IPN_SO_MSGPOOLSIZE:
2084 + val=ipnn->msgpool_size;
2085 + else if (ipn_node->pbp)
2086 + val=ipn_node->pbp->msgpoolsize;
2088 + case IPN_SO_FLAGS:
2091 + else if (ipn_node->pbp)
2092 + val=ipn_node->pbp->flags;
2097 + else if (ipn_node->pbp)
2098 + val=ipn_node->pbp->mode;
2104 + if (len < sizeof(int))
2105 + return -EOVERFLOW;
2107 + len = sizeof(int);
2108 + if(put_user(len, optlen))
2110 + if(copy_to_user(optval,&val,len))
2119 +/* BROADCAST/HUB implementation */
2121 +static int ipn_bcast_newport(struct ipn_node *newport) {
2122 + struct ipn_network *ipnn=newport->ipn;
2124 + for (i=0;i<ipnn->maxports;i++) {
2125 + if (ipnn->connport[i] == NULL)
2131 +static int ipn_bcast_handlemsg(struct ipn_node *from,
2132 + struct msgpool_item *msgitem){
2133 + struct ipn_network *ipnn=from->ipn;
2135 + struct ipn_node *ipn_node;
2136 + list_for_each_entry(ipn_node, &ipnn->connectqueue, nodelist) {
2137 + if (ipn_node != from)
2138 + ipn_proto_sendmsg(ipn_node,msgitem);
2143 +static void ipn_null_delport(struct ipn_node *oldport) {}
2144 +static void ipn_null_postnewport(struct ipn_node *newport) {}
2145 +static void ipn_null_predelport(struct ipn_node *oldport) {}
2146 +static int ipn_null_newnet(struct ipn_network *newnet) {return 0;}
2147 +static int ipn_null_resizenet(struct ipn_network *net,int oldsize,int newsize) {
2149 +static void ipn_null_delnet(struct ipn_network *oldnet) {}
2150 +static int ipn_null_setsockopt(struct ipn_node *port,int optname,
2151 + char __user *optval, int optlen) {return -EOPNOTSUPP;}
2152 +static int ipn_null_getsockopt(struct ipn_node *port,int optname,
2153 + char __user *optval, int *optlen) {return -EOPNOTSUPP;}
2154 +static int ipn_null_ioctl(struct ipn_node *port,unsigned int request,
2155 + unsigned long arg) {return -EOPNOTSUPP;}
2157 +/* Protocol Registration/deregisteration */
2159 +void ipn_init_protocol(struct ipn_protocol *p)
2161 + if (p->ipn_p_delport == NULL) p->ipn_p_delport=ipn_null_delport;
2162 + if (p->ipn_p_postnewport == NULL) p->ipn_p_postnewport=ipn_null_postnewport;
2163 + if (p->ipn_p_predelport == NULL) p->ipn_p_predelport=ipn_null_predelport;
2164 + if (p->ipn_p_newnet == NULL) p->ipn_p_newnet=ipn_null_newnet;
2165 + if (p->ipn_p_resizenet == NULL) p->ipn_p_resizenet=ipn_null_resizenet;
2166 + if (p->ipn_p_delnet == NULL) p->ipn_p_delnet=ipn_null_delnet;
2167 + if (p->ipn_p_setsockopt == NULL) p->ipn_p_setsockopt=ipn_null_setsockopt;
2168 + if (p->ipn_p_getsockopt == NULL) p->ipn_p_getsockopt=ipn_null_getsockopt;
2169 + if (p->ipn_p_ioctl == NULL) p->ipn_p_ioctl=ipn_null_ioctl;
2172 +int ipn_proto_register(int protocol,struct ipn_protocol *ipn_service)
2175 + if (ipn_service->ipn_p_newport == NULL ||
2176 + ipn_service->ipn_p_handlemsg == NULL)
2178 + ipn_init_protocol(ipn_service);
2179 + if (down_interruptible(&ipn_glob_mutex))
2180 + return -ERESTARTSYS;
2181 + if (protocol > 1 && protocol <= IPN_MAX_PROTO) {
2183 + if (ipn_protocol_table[protocol])
2186 + ipn_service->refcnt=0;
2187 + ipn_protocol_table[protocol]=ipn_service;
2188 + printk(KERN_INFO "IPN: Registered protocol %d\n",protocol+1);
2192 + up(&ipn_glob_mutex);
2196 +int ipn_proto_deregister(int protocol)
2199 + if (down_interruptible(&ipn_glob_mutex))
2200 + return -ERESTARTSYS;
2201 + if (protocol > 1 && protocol <= IPN_MAX_PROTO) {
2203 + if (ipn_protocol_table[protocol]) {
2204 + if (ipn_protocol_table[protocol]->refcnt == 0) {
2205 + ipn_protocol_table[protocol]=NULL;
2206 + printk(KERN_INFO "IPN: Unregistered protocol %d\n",protocol+1);
2213 + up(&ipn_glob_mutex);
2218 +/* Module constructor/destructor */
2219 +static struct net_proto_family ipn_family_ops = {
2221 + .create = ipn_create,
2222 + .owner = THIS_MODULE,
2225 +/* IPN constructor */
2226 +static int ipn_init(void)
2230 + ipn_init_protocol(&ipn_bcast);
2231 + ipn_network_cache=kmem_cache_create("ipn_network",sizeof(struct ipn_network),0,0,NULL);
2232 + if (!ipn_network_cache) {
2233 + printk(KERN_CRIT "%s: Cannot create ipn_network SLAB cache!\n",
2239 + ipn_node_cache=kmem_cache_create("ipn_node",sizeof(struct ipn_node),0,0,NULL);
2240 + if (!ipn_node_cache) {
2241 + printk(KERN_CRIT "%s: Cannot create ipn_node SLAB cache!\n",
2247 + ipn_msgitem_cache=kmem_cache_create("ipn_msgitem",sizeof(struct msgitem),0,0,NULL);
2248 + if (!ipn_msgitem_cache) {
2249 + printk(KERN_CRIT "%s: Cannot create ipn_msgitem SLAB cache!\n",
2252 + goto out_net_node;
2255 + rc=ipn_msgbuf_init();
2257 + printk(KERN_CRIT "%s: Cannot create ipn_msgbuf SLAB cache\n",
2259 + goto out_net_node_msg;
2262 + rc=proto_register(&ipn_proto,1);
2264 + printk(KERN_CRIT "%s: Cannot register the protocol!\n",
2266 + goto out_net_node_msg_msgbuf;
2269 + sock_register(&ipn_family_ops);
2270 + ipn_netdev_init();
2271 + printk(KERN_INFO "IPN: Virtual Square Project, University of Bologna 2007\n");
2274 +out_net_node_msg_msgbuf:
2275 + ipn_msgbuf_fini();
2277 + kmem_cache_destroy(ipn_msgitem_cache);
2279 + kmem_cache_destroy(ipn_node_cache);
2281 + kmem_cache_destroy(ipn_network_cache);
2286 +/* IPN destructor */
2287 +static void ipn_exit(void)
2289 + ipn_netdev_fini();
2290 + if (ipn_msgitem_cache)
2291 + kmem_cache_destroy(ipn_msgitem_cache);
2292 + if (ipn_node_cache)
2293 + kmem_cache_destroy(ipn_node_cache);
2294 + if (ipn_network_cache)
2295 + kmem_cache_destroy(ipn_network_cache);
2296 + ipn_msgbuf_fini();
2297 + sock_unregister(PF_IPN);
2298 + proto_unregister(&ipn_proto);
2299 + printk(KERN_INFO "IPN removed\n");
2302 +module_init(ipn_init);
2303 +module_exit(ipn_exit);
2305 +EXPORT_SYMBOL_GPL(ipn_proto_register);
2306 +EXPORT_SYMBOL_GPL(ipn_proto_deregister);
2307 +EXPORT_SYMBOL_GPL(ipn_proto_sendmsg);
2308 +EXPORT_SYMBOL_GPL(ipn_proto_oobsendmsg);
2309 +EXPORT_SYMBOL_GPL(ipn_msgpool_alloc);
2310 +EXPORT_SYMBOL_GPL(ipn_msgpool_put);
2311 diff -Naur linux-2.6.28.2/net/ipn/ipn_msgbuf.c linux-2.6.28.2-ipn/net/ipn/ipn_msgbuf.c
2312 --- linux-2.6.28.2/net/ipn/ipn_msgbuf.c 1970-01-01 01:00:00.000000000 +0100
2313 +++ linux-2.6.28.2-ipn/net/ipn/ipn_msgbuf.c 2009-02-01 13:30:09.000000000 +0100
2316 + * Inter process networking (virtual distributed ethernet) module
2317 + * management of ipn_msgbuf (one slab for each MTU)
2318 + * (part of the View-OS project: wiki.virtualsquare.org)
2320 + * N.B. all these functions need global locking! (ipn_glob_lock)
2322 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
2324 + * This program is free software; you can redistribute it and/or modify
2325 + * it under the terms of the GNU General Public License as published by
2326 + * the Free Software Foundation; either version 2 of the License, or
2327 + * (at your option) any later version.
2329 + * Due to this file being licensed under the GPL there is controversy over
2330 + * whether this permits you to write a module that #includes this file
2331 + * without placing your module under the GPL. Please consult a lawyer for
2332 + * advice before doing this.
2334 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2338 +#include <linux/init.h>
2339 +#include <linux/module.h>
2341 +#include <net/af_ipn.h>
2342 +#include "ipn_netdev.h"
2344 +struct ipn_msgbuf {
2345 + struct list_head list;
2348 + char cachename[12];
2349 + struct kmem_cache *cache;
2352 +static LIST_HEAD(ipn_msgbufh);
2353 +static struct kmem_cache *ipn_msgbuf_cache;
2355 +/* get a kmem_cache pointer for a given mtu.
2356 + * it is a cache for struct msgpool_item elements (the latter field of
2357 + * the struct, i.e. the payload, has variable length depending on the mtu)
2358 + * if it exists already a cache with the given mtu, ipn_msgbuf_get creates
2359 + * one more reference for that cache, otherwise a new one is created.
2361 +struct kmem_cache *ipn_msgbuf_get(int mtu)
2363 + struct ipn_msgbuf *ipn_msgbuf;
2364 + list_for_each_entry(ipn_msgbuf, &ipn_msgbufh, list) {
2365 + if (mtu == ipn_msgbuf->mtu) {
2366 + ipn_msgbuf->refcnt++;
2367 + return ipn_msgbuf->cache;
2370 + ipn_msgbuf=kmem_cache_alloc(ipn_msgbuf_cache,GFP_KERNEL);
2371 + if (ipn_msgbuf == NULL)
2374 + ipn_msgbuf->mtu=mtu;
2375 + ipn_msgbuf->refcnt=1;
2376 + snprintf(ipn_msgbuf->cachename,12,"ipn%d",mtu);
2377 + ipn_msgbuf->cache=kmem_cache_create(ipn_msgbuf->cachename,sizeof(struct msgpool_item)+mtu,0,0,NULL);
2378 + list_add_tail(&ipn_msgbuf->list,&ipn_msgbufh);
2379 + return ipn_msgbuf->cache;
2383 +/* release a reference of a msgbuf cache (a network with a given mtu
2384 + * is terminating).
2385 + * the last reference for a given mtu releases the slub*/
2386 +void ipn_msgbuf_put(struct kmem_cache *cache)
2388 + struct ipn_msgbuf *ipn_msgbuf;
2389 + list_for_each_entry(ipn_msgbuf, &ipn_msgbufh, list) {
2390 + if (ipn_msgbuf->cache == cache) {
2391 + ipn_msgbuf->refcnt--;
2392 + if (ipn_msgbuf->refcnt == 0) {
2393 + kmem_cache_destroy(ipn_msgbuf->cache);
2394 + list_del(&ipn_msgbuf->list);
2395 + kmem_cache_free(ipn_msgbuf_cache,ipn_msgbuf);
2402 +int ipn_msgbuf_init(void)
2404 + ipn_msgbuf_cache=kmem_cache_create("ipn_msgbuf",sizeof(struct ipn_msgbuf),0,0,NULL);
2405 + if (!ipn_msgbuf_cache)
2411 +void ipn_msgbuf_fini(void)
2413 + if (ipn_msgbuf_cache) {
2414 + while (!list_empty(&ipn_msgbufh)) {
2415 + struct ipn_msgbuf *ipn_msgbuf=list_first_entry(&ipn_msgbufh, struct ipn_msgbuf, list);
2416 + list_del(&ipn_msgbuf->list);
2417 + kmem_cache_destroy(ipn_msgbuf->cache);
2418 + kmem_cache_free(ipn_msgbuf_cache,ipn_msgbuf);
2420 + kmem_cache_destroy(ipn_msgbuf_cache);
2423 diff -Naur linux-2.6.28.2/net/ipn/ipn_msgbuf.h linux-2.6.28.2-ipn/net/ipn/ipn_msgbuf.h
2424 --- linux-2.6.28.2/net/ipn/ipn_msgbuf.h 1970-01-01 01:00:00.000000000 +0100
2425 +++ linux-2.6.28.2-ipn/net/ipn/ipn_msgbuf.h 2009-02-01 13:30:09.000000000 +0100
2428 + * Inter process networking (virtual distributed ethernet) module
2429 + * management of msgbuf (one slab for each MTU)
2430 + * (part of the View-OS project: wiki.virtualsquare.org)
2432 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
2434 + * This program is free software; you can redistribute it and/or modify
2435 + * it under the terms of the GNU General Public License as published by
2436 + * the Free Software Foundation; either version 2 of the License, or
2437 + * (at your option) any later version.
2439 + * Due to this file being licensed under the GPL there is controversy over
2440 + * whether this permits you to write a module that #includes this file
2441 + * without placing your module under the GPL. Please consult a lawyer for
2442 + * advice before doing this.
2444 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2448 +#ifndef _IPN_MSGBUF_H
2449 +#define _IPN_MSGBUF_H
2451 +struct kmem_cache *ipn_msgbuf_get(int mtu);
2452 +void ipn_msgbuf_put(struct kmem_cache *cache);
2453 +int ipn_msgbuf_init(void);
2454 +void ipn_msgbuf_fini(void);
2457 diff -Naur linux-2.6.28.2/net/ipn/ipn_netdev.c linux-2.6.28.2-ipn/net/ipn/ipn_netdev.c
2458 --- linux-2.6.28.2/net/ipn/ipn_netdev.c 1970-01-01 01:00:00.000000000 +0100
2459 +++ linux-2.6.28.2-ipn/net/ipn/ipn_netdev.c 2009-02-01 13:30:09.000000000 +0100
2462 + * Inter process networking (virtual distributed ethernet) module
2463 + * Net devices: tap and grab
2464 + * (part of the View-OS project: wiki.virtualsquare.org)
2466 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
2468 + * This program is free software; you can redistribute it and/or modify
2469 + * it under the terms of the GNU General Public License as published by
2470 + * the Free Software Foundation; either version 2 of the License, or
2471 + * (at your option) any later version.
2473 + * Due to this file being licensed under the GPL there is controversy over
2474 + * whether this permits you to write a module that #includes this file
2475 + * without placing your module under the GPL. Please consult a lawyer for
2476 + * advice before doing this.
2478 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2482 +#include <linux/init.h>
2483 +#include <linux/module.h>
2484 +#include <linux/socket.h>
2485 +#include <linux/poll.h>
2486 +#include <linux/un.h>
2487 +#include <linux/list.h>
2488 +#include <linux/mount.h>
2489 +#include <linux/etherdevice.h>
2490 +#include <linux/ethtool.h>
2491 +#include <linux/version.h>
2492 +#include <net/sock.h>
2493 +#include <net/af_ipn.h>
2494 +#include "ipn_netdev.h"
2496 +#define DRV_NAME "ipn"
2497 +#define DRV_VERSION "0.3"
2499 +static const struct ethtool_ops ipn_ethtool_ops;
2502 + struct ipn_node *ipn_node;
2503 + struct net_device_stats stats;
2506 +/* TAP Net device open. */
2507 +static int ipntap_net_open(struct net_device *dev)
2509 + netif_start_queue(dev);
2513 +/* TAP Net device close. */
2514 +static int ipntap_net_close(struct net_device *dev)
2516 + netif_stop_queue(dev);
2520 +static struct net_device_stats *ipntap_net_stats(struct net_device *dev)
2522 + struct ipntap *ipntap = netdev_priv(dev);
2523 + return &ipntap->stats;
2526 +/* receive from a TAP */
2527 +static int ipn_net_xmit(struct sk_buff *skb, struct net_device *dev)
2529 + struct ipntap *ipntap = netdev_priv(dev);
2530 + struct ipn_node *ipn_node=ipntap->ipn_node;
2531 + struct msgpool_item *newmsg;
2532 + if (!ipn_node || !ipn_node->ipn || skb->len > ipn_node->ipn->mtu)
2534 + newmsg=ipn_msgpool_alloc(ipn_node->ipn,1);
2537 + newmsg->len=skb->len;
2538 + memcpy(newmsg->data,skb->data,skb->len);
2539 + ipn_proto_injectmsg(ipntap->ipn_node,newmsg);
2540 + ipn_msgpool_put(newmsg,ipn_node->ipn);
2541 + ipntap->stats.tx_packets++;
2542 + ipntap->stats.tx_bytes += skb->len;
2547 + ipntap->stats.tx_dropped++;
2552 +/* receive from a GRAB via interface hook */
2553 +struct sk_buff *ipn_handle_hook(struct ipn_node *ipn_node, struct sk_buff *skb)
2555 + char *data=(skb->data)-(skb->mac_len);
2556 + int len=skb->len+skb->mac_len;
2559 + ((ipn_node->flags & IPN_NODEFLAG_DEVMASK) == IPN_NODEFLAG_GRAB) &&
2560 + ipn_node->ipn && len<=ipn_node->ipn->mtu) {
2561 + struct msgpool_item *newmsg;
2562 + newmsg=ipn_msgpool_alloc(ipn_node->ipn,1);
2565 + memcpy(newmsg->data,data,len);
2566 + ipn_proto_injectmsg(ipn_node,newmsg);
2567 + ipn_msgpool_put(newmsg,ipn_node->ipn);
2574 +static void ipntap_setup(struct net_device *dev)
2576 + dev->open = ipntap_net_open;
2577 + dev->hard_start_xmit = ipn_net_xmit;
2578 + dev->stop = ipntap_net_close;
2579 + dev->get_stats = ipntap_net_stats;
2580 + dev->ethtool_ops = &ipn_ethtool_ops;
2584 +struct net_device *ipn_netdev_alloc(struct net *net,int type, char *name, int *err)
2586 + struct net_device *dev=NULL;
2588 + if (!name || *name==0)
2591 + case IPN_NODEFLAG_TAP:
2592 + dev=alloc_netdev(sizeof(struct ipntap), name, ipntap_setup);
2596 + /* this commented code is similar to tuntap MAC assignment.
2597 + * why tuntap does not use the random_ether_addr?
2598 + *(u16 *)dev->dev_addr = htons(0x00FF);
2599 + get_random_bytes(dev->dev_addr + sizeof(u16), 4);*/
2600 + random_ether_addr((u8 *)&dev->dev_addr);
2602 + case IPN_NODEFLAG_GRAB:
2603 + dev=dev_get_by_name(net,name);
2605 + if (dev->flags & IFF_LOOPBACK)
2607 + else if (rcu_dereference(dev->ipn_port) != NULL)
2617 +int ipn_netdev_activate(struct ipn_node *ipn_node)
2620 + switch (ipn_node->flags & IPN_NODEFLAG_DEVMASK) {
2621 + case IPN_NODEFLAG_TAP:
2623 + struct ipntap *ipntap=netdev_priv(ipn_node->dev);
2624 + ipntap->ipn_node=ipn_node;
2626 + if ((rv=register_netdevice(ipn_node->dev)) == 0)
2627 + rcu_assign_pointer(ipn_node->dev->ipn_port,
2630 + if (rv) {/* error! */
2631 + ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
2632 + free_netdev(ipn_node->dev);
2636 + case IPN_NODEFLAG_GRAB:
2638 + rcu_assign_pointer(ipn_node->dev->ipn_port,
2640 + dev_set_promiscuity(ipn_node->dev,1);
2648 +void ipn_netdev_close(struct ipn_node *ipn_node)
2650 + switch (ipn_node->flags & IPN_NODEFLAG_DEVMASK) {
2651 + case IPN_NODEFLAG_TAP:
2652 + ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
2654 + rcu_assign_pointer(ipn_node->dev->ipn_port, NULL);
2655 + unregister_netdevice(ipn_node->dev);
2657 + free_netdev(ipn_node->dev);
2659 + case IPN_NODEFLAG_GRAB:
2660 + ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
2662 + rcu_assign_pointer(ipn_node->dev->ipn_port, NULL);
2663 + dev_set_promiscuity(ipn_node->dev,-1);
2669 +void ipn_netdev_sendmsg(struct ipn_node *to,struct msgpool_item *msg)
2671 + struct sk_buff *skb;
2672 + struct net_device *dev=to->dev;
2673 + struct ipntap *ipntap=netdev_priv(dev);
2675 + if (msg->len > dev->mtu)
2677 + skb=alloc_skb(msg->len+NET_IP_ALIGN,GFP_KERNEL);
2679 + ipntap->stats.rx_dropped++;
2682 + memcpy(skb_put(skb,msg->len),msg->data,msg->len);
2683 + switch (to->flags & IPN_NODEFLAG_DEVMASK) {
2684 + case IPN_NODEFLAG_TAP:
2685 + skb->protocol = eth_type_trans(skb, dev);
2687 + ipntap->stats.rx_packets++;
2688 + ipntap->stats.rx_bytes += msg->len;
2690 + case IPN_NODEFLAG_GRAB:
2692 + dev_queue_xmit(skb);
2697 +/* ethtool interface */
2699 +static int ipn_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
2701 + cmd->supported = 0;
2702 + cmd->advertising = 0;
2703 + cmd->speed = SPEED_10;
2704 + cmd->duplex = DUPLEX_FULL;
2705 + cmd->port = PORT_TP;
2706 + cmd->phy_address = 0;
2707 + cmd->transceiver = XCVR_INTERNAL;
2708 + cmd->autoneg = AUTONEG_DISABLE;
2709 + cmd->maxtxpkt = 0;
2710 + cmd->maxrxpkt = 0;
2714 +static void ipn_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
2716 + strcpy(info->driver, DRV_NAME);
2717 + strcpy(info->version, DRV_VERSION);
2718 + strcpy(info->fw_version, "N/A");
2721 +static const struct ethtool_ops ipn_ethtool_ops = {
2722 + .get_settings = ipn_get_settings,
2723 + .get_drvinfo = ipn_get_drvinfo,
2724 + /* not implemented (yet?)
2725 + .get_msglevel = ipn_get_msglevel,
2726 + .set_msglevel = ipn_set_msglevel,
2727 + .get_link = ipn_get_link,
2728 + .get_rx_csum = ipn_get_rx_csum,
2729 + .set_rx_csum = ipn_set_rx_csum */
2732 +int ipn_netdev_init(void)
2734 + ipn_handle_frame_hook=
2735 +#ifdef IPN_STEALING
2743 +void ipn_netdev_fini(void)
2745 + ipn_handle_frame_hook=NULL;
2747 diff -Naur linux-2.6.28.2/net/ipn/ipn_netdev.h linux-2.6.28.2-ipn/net/ipn/ipn_netdev.h
2748 --- linux-2.6.28.2/net/ipn/ipn_netdev.h 1970-01-01 01:00:00.000000000 +0100
2749 +++ linux-2.6.28.2-ipn/net/ipn/ipn_netdev.h 2009-02-01 13:30:09.000000000 +0100
2751 +#ifndef _IPN_NETDEV_H
2752 +#define _IPN_NETDEV_H
2754 + * Inter process networking (virtual distributed ethernet) module
2755 + * Net devices: tap and grab
2756 + * (part of the View-OS project: wiki.virtualsquare.org)
2758 + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
2760 + * This program is free software; you can redistribute it and/or modify
2761 + * it under the terms of the GNU General Public License as published by
2762 + * the Free Software Foundation; either version 2 of the License, or
2763 + * (at your option) any later version.
2765 + * Due to this file being licensed under the GPL there is controversy over
2766 + * whether this permits you to write a module that #includes this file
2767 + * without placing your module under the GPL. Please consult a lawyer for
2768 + * advice before doing this.
2770 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2774 +#include <linux/init.h>
2775 +#include <linux/module.h>
2776 +#include <linux/socket.h>
2777 +#include <linux/poll.h>
2778 +#include <linux/un.h>
2779 +#include <linux/list.h>
2780 +#include <linux/mount.h>
2781 +#include <linux/etherdevice.h>
2782 +#include <linux/if_bridge.h>
2783 +#include <net/sock.h>
2784 +#include <net/af_ipn.h>
2786 +#ifdef IPN_STEALING
2787 +#define ipn_port br_port
2790 +struct net_device *ipn_netdev_alloc(struct net *net,int type, char *name, int *err);
2791 +int ipn_netdev_activate(struct ipn_node *ipn_node);
2792 +void ipn_netdev_close(struct ipn_node *ipn_node);
2793 +void ipn_netdev_sendmsg(struct ipn_node *to,struct msgpool_item *msg);
2794 +int ipn_netdev_init(void);
2795 +void ipn_netdev_fini(void);
2797 +static inline struct ipn_node *ipn_netdev2node(struct net_device *dev)
2799 + return (struct ipn_node *)rcu_dereference(dev->ipn_port);
2802 +static inline void ipn_netdevsync(void)
2804 + synchronize_rcu();