* Updated to release 1.1a "Try before release"
[vde.git] / kernel-patch-ipn / patch-linux-2.6.25.4-ipn
blob8da56d6149aa2b4a35134a7040309e55b8bb3734
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
4 @@ -0,0 +1,310 @@
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.  
20 +Description:
21 +------------
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>
32 +   #include <sys/un.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
44 +IPN_VDESWITCHL3).
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.  
103 +Network Options
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
112 +behavior. 
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).  
130 +Node Options
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
136 +switches).
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
157 +real network.
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
175 +or GRAB). 
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
181 +closed. 
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
200 +is terminated, too. 
202 +When unloading the ipn kernel module, all the persistent flags of interfaces
203 +are cleared.  
205 +Related Work.
206 +-------------
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
221 +channel.
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 {
232 +  int refcnt;
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
260 +protocol.
262 +Only two fields must be initialized in any case: ipn_p_newport and
263 +ipn_p_handlemsg.
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);
293 +....
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
312 +options.
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/
320  S:     Supported
322 +IPN INTER PROCESS NETWORKING
323 +P:     Renzo Davoli
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
329 +S:     Maintained
331  IPX NETWORK LAYER
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
337 @@ -26,7 +26,7 @@
338  struct inode;
339  struct net;
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
349 @@ -717,6 +717,8 @@
350         struct net_bridge_port  *br_port;
351         /* macvlan */
352         struct macvlan_port     *macvlan_port;
353 +       /* ipn */
354 +       struct ipn_node         *ipn_port;
356         /* class/net/name entry */
357         struct device           dev;
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
361 @@ -189,7 +189,8 @@
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
371 @@ -225,6 +226,7 @@
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
382 @@ -0,0 +1,236 @@
383 +#ifndef __LINUX_NET_AFIPN_H
384 +#define __LINUX_NET_AFIPN_H
386 +#define IPN_ANY 0
387 +#define IPN_BROADCAST 1
388 +#define IPN_HUB 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
412 +/* Ioctl defines */
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
426 + * Specific fields:
427 + * @numreaders=number of readers
428 + * @numwriters=number of writers
429 + * */
430 +struct numnode_oob {
431 +       int level;
432 +       int tag;
433 +       int numreaders;
434 +       int numwriters;
437 +#ifdef __KERNEL__
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;
448 +struct ipn_network;
449 +struct pre_bind_parms;
451 +/* 
452 + * ipn_node
453 + *
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
471 + */
472 +struct ipn_node {
473 +       struct list_head nodelist;
474 +       int protocol;
475 +       volatile unsigned char flags;
476 +       unsigned char shutdown;
477 +       char descr[IPN_DESCRLEN];
478 +       int portno;
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;
485 +       struct net *net;
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 */
501 + * ipn_sock
502 + * 
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!
506 + */
508 +struct ipn_sock {
509 +       struct sock sk;
510 +       struct ipn_node *node;
513 +/* 
514 + * ipn_network network descriptor
515 + *
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
528 + * @mtu=MTU
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
533 + */
534 +struct ipn_network {
535 +       struct hlist_node hnode;
536 +       struct list_head unconnectqueue;
537 +       struct list_head connectqueue;
538 +       int refcnt;
539 +       struct dentry   *dentry;
540 +       struct vfsmount   *mnt;
541 +       struct semaphore ipnn_mutex;
542 +       int sunaddr_len;
543 +       struct sockaddr_un sunaddr;
544 +       unsigned int protocol;
545 +       unsigned int flags;
546 +       int numreaders;
547 +       int numwriters;
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
560 + * @count refcount
561 + * @len packet len
562 + * @data payload
563 + */
564 +struct msgpool_item {
565 +       atomic_t count;
566 +       int len;
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);
573 +/* 
574 + * protocol service:
575 + *
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.
589 + */
590 +struct ipn_protocol {
591 +       int refcnt;
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);
617 +#endif
618 +#endif
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
622 @@ -37,6 +37,7 @@
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
633 @@ -19,6 +19,7 @@
634  obj-$(CONFIG_INET)             += ipv4/
635  obj-$(CONFIG_XFRM)             += xfrm/
636  obj-$(CONFIG_UNIX)             += unix/
637 +obj-$(CONFIG_IPN)              += ipn/
638  ifneq ($(CONFIG_IPV6),)
639  obj-y                          += ipv6/
640  endif
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 @@
645                                              int *ret,
646                                              struct net_device *orig_dev)
648 -       if (skb->dev->macvlan_port == NULL)
649 +       if (!skb || skb->dev->macvlan_port == NULL)
650                 return skb;
652         if (*pt_prev) {
653 @@ -1942,6 +1942,32 @@
654  #define handle_macvlan(skb, pt_prev, ret, orig_dev)    (skb)
655  #endif
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,
664 +                                            int *ret,
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)
671 +                return skb;
673 +       if (*pt_prev) {
674 +               *ret = deliver_skb(skb, *pt_prev, orig_dev);
675 +               *pt_prev = NULL;
676 +       }
677 +       return ipn_handle_frame_hook(port, skb);
679 +#else
680 +#define handle_ipn(skb, pt_prev, ret, orig_dev)        (skb)
681 +#endif
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 @@
687  #endif
689         skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
690 -       if (!skb)
691 -               goto out;
692         skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev);
693 +       skb = handle_ipn(skb, &pt_prev, &ret, orig_dev);
694         if (!skb)
695                 goto out;
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
700 @@ -0,0 +1,21 @@
702 +# Unix Domain Sockets
705 +config IPN
706 +       tristate "IPN domain sockets (EXPERIMENTAL)"
707 +       depends on EXPERIMENTAL
708 +       ---help---
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
712 +         among processes. 
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
718 +         called ipn.  
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
725 @@ -0,0 +1,8 @@
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
737 @@ -0,0 +1,1585 @@
739 + * Main inter process networking (virtual distributed ethernet) module
740 + *  (part of the View-OS project: wiki.virtualsquare.org) 
741 + *
742 + * Copyright (C) 2007   Renzo Davoli (renzo@cs.unibo.it)
743 + *
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.
748 + *
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.
753 + *
754 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
755 + *
756 + */
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 
789 + * comment *IPNTL*
790 + * DEFINE_SPINLOCK(ipn_table_lock);
791 + */
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 = {
804 +       .refcnt=0,
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)
856 +                       goto found;
857 +       }
858 +       ipnn = NULL;
859 +found:
860 +       /* *IPNTL* spin_unlock(&ipn_table_lock); */
861 +       return ipnn;
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*/
873 +struct msgitem {
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 
883 + *  ipn_msgpool_put
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
886 + * receivers */
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);
893 +       }
894 +       return new;
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)
901 +                       return NULL;
902 +               else 
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))
914 +                               return NULL;
915 +               }
916 +       }
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);
934 +       }
937 +/* socket calls */
938 +static const struct proto_ops ipn_ops = {
939 +       .family = PF_IPN,
940 +       .owner =  THIS_MODULE,
941 +       .release =  ipn_release,
942 +       .bind =   ipn_bind,
943 +       .connect =  ipn_connect,
944 +       .socketpair = sock_no_socketpair,
945 +       .accept = sock_no_accept,
946 +       .getname =  ipn_getname,
947 +       .poll =   ipn_poll,
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 = {
960 +       .name   = "IPN",
961 +       .owner    = THIS_MODULE,
962 +       .obj_size = sizeof(struct ipn_sock),
965 +/* create a socket
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;
972 +       
973 +       if (net != &init_net)
974 +               return -EAFNOSUPPORT;
976 +       if (sock->type != SOCK_RAW)
977 +               return -EPROTOTYPE;
978 +       if (protocol > 0)
979 +               protocol=protocol-1;
980 +       else
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);
987 +       if (!ipn_sk) 
988 +               return -ENOMEM;
989 +       ipn_sk->node=ipn_node=kmem_cache_alloc(ipn_node_cache,GFP_KERNEL);
990 +       if (!ipn_node) {
991 +               sock_put((struct sock *) ipn_sk);
992 +               return -ENOMEM;
993 +       }
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;
1015 +       return 0;
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))
1026 +       {
1027 +               struct msgpool_item *ipn_msg=_ipn_msgpool_alloc(ipnn);
1028 +               if (ipn_msg) {
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);
1039 +                       }
1040 +                       ipn_msgpool_put(ipn_msg,ipnn);
1041 +               }
1042 +       }
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);
1058 +       }
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);
1076 +       }
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;
1085 +       if (ipnn) {
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;
1091 +               }
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 */
1106 +               ipnn->refcnt--;
1107 +               if (ipnn->refcnt == 0)
1108 +               {
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);
1115 +                       }
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);
1122 +               }
1123 +       }
1124 +       if (ipn_node->pbp) {
1125 +               kfree(ipn_node->pbp);
1126 +               ipn_node->pbp=NULL;
1127 +       } 
1128 +       return 0;
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;
1136 +       int rv;
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;
1141 +               rv=0;
1142 +               up(&ipn_glob_mutex);
1143 +       } else {
1144 +               rv=ipn_terminate_node(ipn_node);
1145 +               up(&ipn_glob_mutex);
1146 +               if (rv==0) {
1147 +                       ipn_netdevsync();
1148 +                       kmem_cache_free(ipn_node_cache,ipn_node);
1149 +               }
1150 +       }
1151 +       if (rv==0) 
1152 +               sock_put((struct sock *) ipn_sk);
1153 +       return rv;
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)
1162 +       int rv=0;
1163 +       if (persist)
1164 +               ipn_node->flags |= IPN_NODEFLAG_PERSIST;
1165 +       else {
1166 +               ipn_node->flags &= ~IPN_NODEFLAG_PERSIST;
1167 +               if (!(ipn_node->flags & IPN_NODEFLAG_INUSE)) {
1168 +                       rv=ipn_terminate_node(ipn_node);
1169 +                       if (rv==0)
1170 +                               kmem_cache_free(ipn_node_cache,ipn_node);
1171 +               }
1172 +       }
1173 +       return rv;
1176 +/* ipn_setpersist 
1177 + * lock ipn_glob_mutex and call __ipn_setpersist above */
1178 +static int ipn_setpersist(struct ipn_node *ipn_node, int persist)
1180 +       int rv=0;
1181 +       if (ipn_node->dev == NULL)
1182 +               return -ENODEV;
1183 +       if (down_interruptible(&ipn_glob_mutex))
1184 +               return -ERESTARTSYS;
1185 +       rv=_ipn_setpersist(ipn_node,persist);
1186 +       up(&ipn_glob_mutex);
1187 +       return rv;
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))
1208 +               return -EINVAL;
1209 +       if (!sunaddr || sunaddr->sun_family != AF_IPN)
1210 +               return -EINVAL;
1211 +       /*
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.
1217 +        */
1218 +       ((char *)sunaddr)[len]=0;
1219 +       len = strlen(sunaddr->sun_path)+1+sizeof(short);
1220 +       return len;
1223 +/* IPN BIND */
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;
1231 +       int err;
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) {
1240 +               err= -EISCONN;
1241 +               goto out;
1242 +       }
1244 +       if (ipn_node->protocol >= 0 && 
1245 +                       (ipn_node->protocol >= IPN_MAX_PROTO ||
1246 +                        ipn_protocol_table[ipn_node->protocol] == NULL)) {
1247 +               err= -EPROTONOSUPPORT;
1248 +               goto out;
1249 +       }
1251 +       addr_len = ipn_mkname(sunaddr, addr_len);
1252 +       if (addr_len < 0) {
1253 +               err=addr_len;
1254 +               goto out;
1255 +       }
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);
1263 +               if (err)
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;
1270 +               /*
1271 +                * All right, let's create it.
1272 +                */
1273 +               if (ipn_node->pbp) 
1274 +                       mode = ipn_node->pbp->mode;
1275 +               else
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);
1279 +               if (err)
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); 
1288 +               if (!ipnn) {
1289 +                       err=-ENOMEM;
1290 +                       goto out_mknod_dput_ipnn;
1291 +               }
1292 +               ipnn->connport=kzalloc(parms.maxports * sizeof(struct ipn_node *),GFP_KERNEL);
1293 +               if (!ipnn->connport) {
1294 +                       err=-ENOMEM;
1295 +                       goto out_mknod_dput_ipnn2;
1296 +               }
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)) {
1301 +                       err = -EINVAL;
1302 +                       goto out_mknod_dput_ipnn2;
1303 +               }
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) {
1308 +                       err=-ENOMEM;
1309 +                       goto out_mknod_dput_putmodule;
1310 +               }
1311 +               INIT_LIST_HEAD(&ipnn->unconnectqueue);
1312 +               INIT_LIST_HEAD(&ipnn->connectqueue);
1313 +               ipnn->refcnt=1;
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);
1330 +               if (err)
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);
1333 +       } else {
1334 +               /* join an existing network */
1335 +               if (parms.flags & IPN_FLAG_EXCL) {
1336 +                       err=-EEXIST;
1337 +                       goto put_fail;
1338 +               }
1339 +               err = vfs_permission(&nd, MAY_EXEC);
1340 +               if (err)
1341 +                       goto put_fail;
1342 +               err = -ECONNREFUSED;
1343 +               if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode))
1344 +                       goto put_fail;
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))
1348 +                       goto put_fail;
1349 +               list_add_tail(&ipn_node->nodelist,&ipnn->unconnectqueue);
1350 +               ipnn->refcnt++;
1351 +       }
1352 +       if (ipn_node->pbp) {
1353 +               kfree(ipn_node->pbp);
1354 +               ipn_node->pbp=NULL;
1355 +       } 
1356 +       ipn_node->ipn=ipnn;
1357 +       ipn_node->flags |= IPN_NODEFLAG_BOUND;
1358 +       up(&ipn_glob_mutex);
1359 +       return 0;
1361 +put_fail:
1362 +       path_put(&nd.path);
1363 +out:
1364 +       up(&ipn_glob_mutex);
1365 +       return err;
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);
1373 +out_mknod_dput:
1374 +       dput(dentry);
1375 +out_mknod_unlock:
1376 +       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
1377 +       path_put(&nd.path);
1378 +out_mknod_parent:
1379 +       if (err==-EEXIST)
1380 +               err=-EADDRINUSE;
1381 +       up(&ipn_glob_mutex);
1382 +       return err;
1385 +/* IPN CONNECT */
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;
1392 +       int err=0;
1393 +       int portno;
1395 +       /* the socket cannot be connected twice */
1396 +       if (sock->state != SS_UNCONNECTED) 
1397 +               return EISCONN;
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);
1405 +               if (err < 0)
1406 +                       goto out;
1407 +               addr_len=err;
1408 +               err = path_lookup(sunaddr->sun_path, LOOKUP_FOLLOW, &nd);
1409 +               if (err)
1410 +                       goto out;
1411 +               err = vfs_permission(&nd, MAY_READ);
1412 +               if (err) {
1413 +                       if (err == -EACCES || err == -EROFS)
1414 +                               mustshutdown|=RCV_SHUTDOWN;
1415 +                       else
1416 +                               goto put_fail;
1417 +               }
1418 +               err = vfs_permission(&nd, MAY_WRITE);
1419 +               if (err) {
1420 +                       if (err == -EACCES)
1421 +                               mustshutdown|=SEND_SHUTDOWN;
1422 +                       else
1423 +                               goto put_fail;
1424 +               }
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) {
1429 +                       err=-EACCES;
1430 +                       goto put_fail;
1431 +               } else {
1432 +                       err=0;
1433 +                       ipn_node->shutdown=mustshutdown;
1434 +               }
1435 +               if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode)) {
1436 +                       err = -ECONNREFUSED;
1437 +                       goto put_fail;
1438 +               }
1439 +               ipnn=ipn_find_network_byinode(nd.path.dentry->d_inode);
1440 +               if (!ipnn || (ipnn->flags & IPN_FLAG_TERMINATED)) {
1441 +                       err = -ECONNREFUSED;
1442 +                       goto put_fail;
1443 +               }
1444 +               if (ipn_node->protocol == IPN_ANY)
1445 +                       ipn_node->protocol=ipnn->protocol;
1446 +               else if (ipnn->protocol != ipn_node->protocol) {
1447 +                       err = -EPROTO;
1448 +                       goto put_fail;
1449 +               }
1450 +               path_put(&nd.path);
1451 +               ipn_node->ipn=ipnn;
1452 +       } else
1453 +               ipnn=ipn_node->ipn;
1455 +       if (down_interruptible(&ipnn->ipnn_mutex)) {
1456 +               err=-ERESTARTSYS;
1457 +               goto out;
1458 +       }
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)) {
1465 +                       ipnn->refcnt++;
1466 +                       list_del(&ipn_node->nodelist);
1467 +               }
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);
1472 +       } else {
1473 +               ipn_node->ipn=previousipnn; /* undo changes on ipn_node->ipn */
1474 +               err=-EADDRNOTAVAIL;
1475 +       }
1476 +       up(&ipnn->ipnn_mutex);
1477 +       up(&ipn_glob_mutex);
1478 +       return err;
1480 +put_fail:
1481 +       path_put(&nd.path);
1482 +out:
1483 +       up(&ipn_glob_mutex);
1484 +       return err;
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;
1492 +       int err=0;
1494 +       if (down_interruptible(&ipn_glob_mutex))
1495 +               return -ERESTARTSYS;
1496 +       if (ipnn) {
1497 +               *uaddr_len = ipnn->sunaddr_len;
1498 +               memcpy(sunaddr,&ipnn->sunaddr,*uaddr_len);
1499 +       } else
1500 +               err = -ENOTCONN;
1501 +       up(&ipn_glob_mutex);
1502 +       return err;
1505 +/* IPN POLL */
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;
1512 +       if (ipnn) {
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;
1524 +       } 
1525 +       return mask;
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)
1532 +       int err=0;
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))
1536 +               return -EPERM;
1537 +       if (sock->state != SS_UNCONNECTED) 
1538 +               return -EISCONN;
1539 +       if (!ipnn)
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;
1546 +       }
1547 +       ipn_node->dev=ipn_netdev_alloc(ipn_node->net,ifr->ifr_flags,ifr->ifr_name,&err);
1548 +       if (ipn_node->dev) {
1549 +               int portno;
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);
1557 +                       if (err) {
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;
1564 +                       } else  {
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);
1568 +                       }
1569 +               } else {
1570 +                       ipn_netdev_close(ipn_node); 
1571 +                       err=-EADDRNOTAVAIL;
1572 +                       ipn_node->dev=NULL;
1573 +               }
1574 +       } else 
1575 +               err=-EINVAL;
1576 +       up(&ipnn->ipnn_mutex);
1577 +       up(&ipn_glob_mutex);
1578 +       return err;
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)
1585 +       int err=0;
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)
1591 +               return -EISCONN;
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;
1597 +       }
1598 +       dev=__dev_get_by_name(ipn_node->net,ifr->ifr_name);
1599 +       if (!dev) 
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 */
1602 +               int i;
1603 +               for (i=0;i<ipnn->maxports && ipn_joined != ipnn->connport[i] ;i++)
1604 +                       ;
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;
1609 +                       ipnn->refcnt--;
1610 +                       kmem_cache_free(ipn_node_cache,ipn_node);
1611 +               } else
1612 +                       err=-EPERM;
1613 +       } else
1614 +               err=-EADDRNOTAVAIL;
1615 +       up(&ipnn->ipnn_mutex);
1616 +       up(&ipn_glob_mutex);
1617 +       return err;
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;
1626 +       int err=0;
1627 +       if (!capable(CAP_NET_ADMIN))
1628 +               return -EPERM;
1629 +       if (down_interruptible(&ipn_glob_mutex))
1630 +               return -ERESTARTSYS;
1631 +       dev=__dev_get_by_name(&init_net,ifr->ifr_name);
1632 +       if (!dev)
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);
1636 +       else
1637 +               err=-EADDRNOTAVAIL;
1638 +       up(&ipn_glob_mutex);
1639 +       return err;
1642 +/* IPN IOCTL */
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;
1647 +       struct ifreq ifr;
1649 +       if (ipn_node->shutdown == SHUTDOWN_XMASK)
1650 +               return -ECONNRESET;
1652 +       /* get arguments */
1653 +       switch (cmd) {
1654 +               case IPN_CHECK:
1655 +                       return IPN_CHECK;
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))
1662 +                               return -EFAULT;
1663 +                       ifr.ifr_name[IFNAMSIZ-1] = '\0';
1664 +       }
1666 +       /* actions for unconnected and unbound sockets */
1667 +       switch (cmd) {
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))
1674 +                               return -EPERM;
1675 +                       if (ipn_node->dev && (ipn_node->flags &IPN_NODEFLAG_TAP))
1676 +                               return dev_set_mac_address(ipn_node->dev, &ifr.ifr_hwaddr);
1677 +                       else
1678 +                               return -EADDRNOTAVAIL;
1679 +       }
1680 +       if (ipnn == NULL || (ipnn->flags & IPN_FLAG_TERMINATED))
1681 +               return -ENOTCONN;
1682 +       /* actions for connected or bound sockets */
1683 +       switch (cmd) {
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);
1690 +               default:
1691 +                       if (ipnn) {
1692 +                               int rv;
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);
1697 +                               return rv;
1698 +                       } else
1699 +                               return -EOPNOTSUPP;
1700 +       }
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;
1713 +       if(ipnn) {
1714 +               if (down_interruptible(&ipnn->ipnn_mutex)) {
1715 +                       ipn_node->shutdown = oldshutdown;
1716 +                       return -ERESTARTSYS;
1717 +               }
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);
1723 +               }
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);
1729 +       }
1730 +       return 0;
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;
1738 +       int err=0;
1739 +       if (down_interruptible(&ipnn->ipnn_mutex))
1740 +               err=-ERESTARTSYS;
1741 +       else {
1742 +               ipn_protocol_table[ipnn->protocol]->ipn_p_handlemsg(from, msg);
1743 +               up(&ipnn->ipnn_mutex);
1744 +       }
1745 +       return err;
1748 +/* SEND MSG */
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;
1754 +       int err=0;
1756 +       if (unlikely(sock->state != SS_CONNECTED)) 
1757 +                       return -ENOTCONN;
1758 +       if (unlikely(ipn_node->shutdown & SEND_SHUTDOWN)) {
1759 +               if (ipn_node->shutdown == SHUTDOWN_XMASK)
1760 +                       return -ECONNRESET;
1761 +               else
1762 +                       return -EPIPE;
1763 +       }
1764 +       if (len > ipnn->mtu)
1765 +               return -EOVERFLOW;
1766 +       newmsg=ipn_msgpool_alloc_locking(ipnn);
1767 +       if (!newmsg)
1768 +               return -ENOMEM;
1769 +       newmsg->len=len;
1770 +       err=memcpy_fromiovec(newmsg->data, msg->msg_iov, len);
1771 +       if (!err) 
1772 +               ipn_proto_injectmsg(ipn_node, newmsg);
1773 +       ipn_msgpool_put(newmsg,ipnn);
1774 +       return err;
1777 +/* enqueue an oob message. "to" is the destination */
1778 +void ipn_proto_oobsendmsg(struct ipn_node *to, struct msgpool_item *msg)
1780 +       if (to) {
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) {
1789 +                                       msgitem->msg=msg;
1790 +                                       to->totmsgcount++;
1791 +                                       to->oobmsgcount++;
1792 +                                       list_add_tail(&msgitem->list, &to->oobmsgqueue);
1793 +                                       ipn_msgpool_hold(msg);
1794 +                               }
1795 +                       }
1796 +                       spin_unlock(&to->msglock);
1797 +                       wake_up_interruptible(&to->read_wait);
1798 +               }
1799 +       }
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)
1806 +       if (to) {
1807 +               if (to->dev) {
1808 +                       ipn_netdev_sendmsg(to,msg);
1809 +               } else {
1810 +                       /* socket send */
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))
1817 +                                       yield();*/
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) {
1821 +                                               msgitem->msg=msg;
1822 +                                               to->totmsgcount++;
1823 +                                               list_add_tail(&msgitem->list, &to->msgqueue);
1824 +                                               ipn_msgpool_hold(msg);
1825 +                                       }
1826 +                               }
1827 +                       }
1828 +                       spin_unlock(&to->msglock);
1829 +                       wake_up_interruptible(&to->read_wait);
1830 +               }
1831 +       }
1834 +/* IPN RECV */
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)) 
1843 +                       return -ENOTCONN;
1845 +       if (unlikely((ipn_node->shutdown & XRCV_SHUTDOWN) == XRCV_SHUTDOWN)) {
1846 +               if (ipn_node->shutdown == SHUTDOWN_XMASK) /*EOF, nothing can be read*/
1847 +                       return 0;
1848 +               else
1849 +                       return -EPIPE; /*trying to read on a write only node */
1850 +       }
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);
1860 +       }
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);
1864 +       else {
1865 +               msgitem=list_first_entry(&ipn_node->oobmsgqueue, struct msgitem, list);
1866 +               msg->msg_flags |= MSG_OOB;
1867 +               ipn_node->oobmsgcount--;
1868 +       }
1869 +       list_del(&msgitem->list);
1870 +       ipn_node->totmsgcount--;
1871 +       spin_unlock(&ipn_node->msglock);
1872 +       currmsg=msgitem->msg;
1873 +       if (currmsg->len < len)
1874 +               len=currmsg->len;
1875 +       memcpy_toiovec(msg->msg_iov, currmsg->data, len);
1876 +       ipn_msgpool_put(currmsg,ipnn);
1877 +       kmem_cache_free(ipn_msgitem_cache,msgitem);
1879 +       return len;
1882 +/* resize a network: change the # of communication ports (connport) */
1883 +static int ipn_netresize(struct ipn_network *ipnn,int newsize)
1885 +       int oldsize,min;
1886 +       struct ipn_node **newconnport;
1887 +       struct ipn_node **oldconnport;
1888 +       int err;
1889 +       if (down_interruptible(&ipnn->ipnn_mutex))
1890 +                       return -ERESTARTSYS;
1891 +       oldsize=ipnn->maxports;
1892 +       if (newsize == oldsize) {
1893 +               up(&ipnn->ipnn_mutex);
1894 +               return 0;
1895 +       }
1896 +       min=oldsize;
1897 +       /* shrink a network. all the ports we are going to eliminate
1898 +        * must be unused! */
1899 +       if (newsize < oldsize) {
1900 +               int i;
1901 +               for (i=newsize; i<oldsize; i++)
1902 +                       if (ipnn->connport[i]) {
1903 +                               up(&ipnn->ipnn_mutex);
1904 +                               return -EADDRINUSE;
1905 +                       }
1906 +               min=newsize;
1907 +       }
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);
1913 +               return -ENOMEM;
1914 +       }
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);
1920 +       if (err) {
1921 +               /* roll back if the resize operation failed for the protocol */
1922 +               ipnn->connport=oldconnport;
1923 +               ipnn->maxports=oldsize;
1924 +               kfree(newconnport);
1925 +       } else 
1926 +               /* successful mission, network resized */
1927 +               kfree(oldconnport);
1928 +       up(&ipnn->ipnn_mutex);
1929 +       return err;
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;
1942 +       if (level > 0) {
1943 +               /* protocol specific sockopt */
1944 +               if (ipnn) {
1945 +                       int rv;
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);
1950 +                       return rv;
1951 +               } else
1952 +                       return -EOPNOTSUPP;
1953 +       } else {
1954 +               if (optname == IPN_SO_DESCR) {
1955 +                       if (optlen > IPN_DESCRLEN)
1956 +                               return -EINVAL;
1957 +                       else {
1958 +                               memset(ipn_node->descr,0,IPN_DESCRLEN);
1959 +                               if (copy_from_user(ipn_node->descr,optval,optlen))
1960 +                                       ipn_node->descr[0]=0;
1961 +                               else
1962 +                                       ipn_node->descr[optlen-1]=0;
1963 +                               return 0;
1964 +                       }
1965 +               } else {
1966 +                       if (optlen < sizeof(int))
1967 +                               return -EINVAL;
1968 +                       else if ((optname & IPN_SO_PREBIND) && (ipnn != NULL))
1969 +                               return -EISCONN;
1970 +                       else {
1971 +                               int val;
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)
1977 +                                               return -ENOMEM;
1978 +                                       *(ipn_node->pbp)=std;
1979 +                               }
1980 +                               switch (optname) {
1981 +                                       case IPN_SO_PORT:
1982 +                                               if (sock->state == SS_UNCONNECTED)
1983 +                                                       ipn_node->portno=val;
1984 +                                               else
1985 +                                                       return -EISCONN;
1986 +                                               break;
1987 +                                       case IPN_SO_CHANGE_NUMNODES:
1988 +                                               if ((ipn_node->flags & IPN_NODEFLAG_BOUND)!=0) {
1989 +                                                       if (val <= 0)
1990 +                                                               return -EINVAL;
1991 +                                                       else
1992 +                                                               return ipn_netresize(ipnn,val);
1993 +                                               } else
1994 +                                                       val=-ENOTCONN;
1995 +                                               break;
1996 +                                       case IPN_SO_WANT_OOB_NUMNODES:
1997 +                                               if (val)
1998 +                                                       ipn_node->flags |= IPN_NODEFLAG_OOB_NUMNODES;
1999 +                                               else
2000 +                                                       ipn_node->flags &= ~IPN_NODEFLAG_OOB_NUMNODES;
2001 +                                               break;
2002 +                                       case IPN_SO_HANDLE_OOB:
2003 +                                               if (val)
2004 +                                                       ipn_node->shutdown &= ~RCV_SHUTDOWN_NO_OOB;
2005 +                                               else
2006 +                                                       ipn_node->shutdown |= RCV_SHUTDOWN_NO_OOB;
2007 +                                               break;
2008 +                                       case IPN_SO_MTU:
2009 +                                               if (val <= 0)
2010 +                                                       return -EINVAL;
2011 +                                               else
2012 +                                                       ipn_node->pbp->mtu=val;
2013 +                                               break;
2014 +                                       case IPN_SO_NUMNODES:
2015 +                                               if (val <= 0)
2016 +                                                       return -EINVAL;
2017 +                                               else
2018 +                                                       ipn_node->pbp->maxports=val;
2019 +                                               break;
2020 +                                       case IPN_SO_MSGPOOLSIZE:
2021 +                                               if (val <= 0)
2022 +                                                       return -EINVAL;
2023 +                                               else
2024 +                                                       ipn_node->pbp->msgpoolsize=val;
2025 +                                               break;
2026 +                                       case IPN_SO_FLAGS:
2027 +                                               ipn_node->pbp->flags=val;
2028 +                                               break;
2029 +                                       case IPN_SO_MODE:
2030 +                                               ipn_node->pbp->mode=val;
2031 +                                               break;
2032 +                               }
2033 +                               return 0;
2034 +                       }
2035 +               }
2036 +       }
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;
2044 +       int len;
2046 +       if (ipn_node->shutdown == SHUTDOWN_XMASK)
2047 +               return -ECONNRESET;
2048 +       if (level != 0 && level != ipn_node->protocol+1)
2049 +               return -EPROTONOSUPPORT;
2050 +       if (level > 0) {
2051 +               if (ipnn) {
2052 +                       int rv;
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);
2058 +                       return rv;
2059 +               } else
2060 +                       return -EOPNOTSUPP;
2061 +       } else {
2062 +               if (get_user(len, optlen))
2063 +                       return -EFAULT;
2064 +               if (optname == IPN_SO_DESCR) {
2065 +                       if (len < IPN_DESCRLEN)
2066 +                               return -EINVAL;
2067 +                       else {
2068 +                               if (len > IPN_DESCRLEN)
2069 +                                       len=IPN_DESCRLEN;
2070 +                               if(put_user(len, optlen))
2071 +                                       return -EFAULT;
2072 +                               if(copy_to_user(optval,ipn_node->descr,len))
2073 +                                       return -EFAULT;
2074 +                               return 0;
2075 +                       }
2076 +               } else {
2077 +                       int val=-2;
2078 +                       switch (optname) {
2079 +                               case IPN_SO_PORT:
2080 +                                       val=ipn_node->portno;
2081 +                                       break;
2082 +                               case IPN_SO_MTU:
2083 +                                       if (ipnn)
2084 +                                               val=ipnn->mtu;
2085 +                                       else if (ipn_node->pbp)
2086 +                                               val=ipn_node->pbp->mtu;
2087 +                                       break;
2088 +                               case IPN_SO_NUMNODES:
2089 +                                       if (ipnn)
2090 +                                               val=ipnn->maxports;
2091 +                                       else if (ipn_node->pbp)
2092 +                                               val=ipn_node->pbp->maxports;
2093 +                                       break;
2094 +                               case IPN_SO_MSGPOOLSIZE:
2095 +                                       if (ipnn)
2096 +                                               val=ipnn->msgpool_size;
2097 +                                       else if (ipn_node->pbp)
2098 +                                               val=ipn_node->pbp->msgpoolsize;
2099 +                                       break;
2100 +                               case IPN_SO_FLAGS:
2101 +                                       if (ipnn)
2102 +                                               val=ipnn->flags;
2103 +                                       else if (ipn_node->pbp)
2104 +                                               val=ipn_node->pbp->flags;
2105 +                                       break;
2106 +                               case IPN_SO_MODE:
2107 +                                       if (ipnn)
2108 +                                               val=-1;
2109 +                                       else if (ipn_node->pbp)
2110 +                                               val=ipn_node->pbp->mode;
2111 +                                       break;
2112 +                       }
2113 +                       if (val < -1)
2114 +                               return -EINVAL;
2115 +                       else {
2116 +                               if (len < sizeof(int))
2117 +                                       return -EOVERFLOW;
2118 +                               else {
2119 +                                       len = sizeof(int);
2120 +                                       if(put_user(len, optlen))
2121 +                                               return -EFAULT;
2122 +                                       if(copy_to_user(optval,&val,len))
2123 +                                               return -EFAULT;
2124 +                                       return 0;
2125 +                               }
2126 +                       }
2127 +               }
2128 +       }
2131 +/* BROADCAST/HUB implementation */
2133 +static int ipn_bcast_newport(struct ipn_node *newport) {
2134 +       struct ipn_network *ipnn=newport->ipn;
2135 +       int i;
2136 +       for (i=0;i<ipnn->maxports;i++) {
2137 +               if (ipnn->connport[i] == NULL) 
2138 +                       return i;
2139 +       }
2140 +       return -1;
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);
2151 +       }
2152 +       return 0;
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) {
2160 +       return 0;}
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)
2186 +       int rv=0;
2187 +       if (ipn_service->ipn_p_newport == NULL ||
2188 +                       ipn_service->ipn_p_handlemsg == NULL)
2189 +               return -EINVAL;
2190 +       ipn_init_protocol(ipn_service);
2191 +       if (down_interruptible(&ipn_glob_mutex)) 
2192 +               return -ERESTARTSYS;
2193 +       if (protocol > 1 && protocol <= IPN_MAX_PROTO) {
2194 +               protocol--;
2195 +               if (ipn_protocol_table[protocol])
2196 +                       rv= -EEXIST;
2197 +               else {
2198 +                       ipn_service->refcnt=0;
2199 +                       ipn_protocol_table[protocol]=ipn_service;
2200 +                       printk(KERN_INFO "IPN: Registered protocol %d\n",protocol+1);
2201 +               }
2202 +       } else
2203 +               rv= -EINVAL;
2204 +       up(&ipn_glob_mutex);
2205 +       return rv;
2208 +int ipn_proto_deregister(int protocol) 
2210 +       int rv=0;
2211 +       if (down_interruptible(&ipn_glob_mutex)) 
2212 +               return -ERESTARTSYS;
2213 +       if (protocol > 1 && protocol <= IPN_MAX_PROTO) {
2214 +               protocol--;
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);
2219 +                       } else
2220 +                               rv=-EADDRINUSE;
2221 +               } else 
2222 +                       rv= -ENOENT;
2223 +       } else
2224 +               rv= -EINVAL;
2225 +       up(&ipn_glob_mutex);
2226 +       return rv;
2229 +/* MAIN SECTION */
2230 +/* Module constructor/destructor */
2231 +static struct net_proto_family ipn_family_ops = {
2232 +       .family = PF_IPN,
2233 +       .create = ipn_create,
2234 +       .owner  = THIS_MODULE,
2237 +/* IPN constructor */
2238 +static int ipn_init(void)
2240 +       int rc;
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",
2246 +                               __FUNCTION__);
2247 +               rc=-ENOMEM;
2248 +               goto out;
2249 +       }
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",
2254 +                               __FUNCTION__);
2255 +               rc=-ENOMEM;
2256 +               goto out_net;
2257 +       }
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",
2262 +                               __FUNCTION__);
2263 +               rc=-ENOMEM;
2264 +               goto out_net_node;
2265 +       }
2267 +       rc=ipn_msgbuf_init();
2268 +       if (rc != 0) {
2269 +               printk(KERN_CRIT "%s: Cannot create ipn_msgbuf SLAB cache\n",
2270 +                               __FUNCTION__);
2271 +               goto out_net_node_msg;
2272 +       }
2274 +       rc=proto_register(&ipn_proto,1);
2275 +       if (rc != 0) {
2276 +               printk(KERN_CRIT "%s: Cannot register the protocol!\n",
2277 +                               __FUNCTION__);
2278 +               goto out_net_node_msg_msgbuf;
2279 +       }
2281 +       sock_register(&ipn_family_ops);
2282 +       ipn_netdev_init();
2283 +       printk(KERN_INFO "IPN: Virtual Square Project, University of Bologna 2007\n");
2284 +       return 0;
2286 +out_net_node_msg_msgbuf:
2287 +       ipn_msgbuf_fini();
2288 +out_net_node_msg:
2289 +       kmem_cache_destroy(ipn_msgitem_cache);
2290 +out_net_node:
2291 +       kmem_cache_destroy(ipn_node_cache);
2292 +out_net:
2293 +       kmem_cache_destroy(ipn_network_cache);
2294 +out:
2295 +       return rc;
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
2326 @@ -0,0 +1,108 @@
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) 
2331 + *
2332 + * N.B. all these functions need global locking! (ipn_glob_lock)
2333 + *
2334 + * Copyright (C) 2007   Renzo Davoli (renzo@cs.unibo.it)
2335 + *
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.
2340 + *
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.
2345 + *
2346 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2347 + *
2348 + */
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;
2358 +       int mtu;
2359 +       int refcnt;
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.
2372 + */
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;
2380 +               }
2381 +       }
2382 +       ipn_msgbuf=kmem_cache_alloc(ipn_msgbuf_cache,GFP_KERNEL);
2383 +       if (ipn_msgbuf == NULL)
2384 +               return NULL;
2385 +       else {
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;
2392 +       }
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);
2408 +                               return;
2409 +                       }
2410 +               }
2411 +       }
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)
2418 +               return -ENOMEM;
2419 +       else
2420 +               return 0;
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);
2431 +               }
2432 +               kmem_cache_destroy(ipn_msgbuf_cache);
2433 +       }
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
2438 @@ -0,0 +1,30 @@
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) 
2443 + *
2444 + * Copyright (C) 2007   Renzo Davoli (renzo@cs.unibo.it)
2445 + *
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.
2450 + *
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.
2455 + *
2456 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2457 + *
2458 + */
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);
2468 +#endif
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
2472 @@ -0,0 +1,286 @@
2474 + * Inter process networking (virtual distributed ethernet) module
2475 + * Net devices: tap and grab
2476 + *  (part of the View-OS project: wiki.virtualsquare.org) 
2477 + *
2478 + * Copyright (C) 2007   Renzo Davoli (renzo@cs.unibo.it)
2479 + *
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.
2484 + *
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.
2489 + *
2490 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2491 + *
2492 + */
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;
2513 +struct ipntap {
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);
2522 +                 return 0;
2525 +/* TAP Net device close. */
2526 +static int ipntap_net_close(struct net_device *dev)
2528 +         netif_stop_queue(dev);
2529 +                 return 0;
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)
2545 +               goto drop;
2546 +       newmsg=ipn_msgpool_alloc(ipn_node->ipn,1);
2547 +       if (!newmsg)
2548 +               goto drop;
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;
2555 +       kfree_skb(skb);
2556 +       return 0;
2558 +drop:
2559 +       ipntap->stats.tx_dropped++;
2560 +       kfree_skb(skb);
2561 +       return 0;
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;
2570 +       if (ipn_node && 
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);
2575 +               if (newmsg) {
2576 +                       newmsg->len=len;
2577 +                       memcpy(newmsg->data,data,len);
2578 +                       ipn_proto_injectmsg(ipn_node,newmsg);
2579 +                       ipn_msgpool_put(newmsg,ipn_node->ipn);
2580 +               }
2581 +       }
2583 +       return (skb);
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;
2599 +       *err=0;
2600 +       if (!name || *name==0) 
2601 +               name="ipn%d";
2602 +       switch (type) {
2603 +               case IPN_NODEFLAG_TAP:
2604 +                       dev=alloc_netdev(sizeof(struct ipntap), name, ipntap_setup);
2605 +                       if (!dev)
2606 +                               *err= -ENOMEM;
2607 +                       ether_setup(dev);
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);
2613 +                       break;
2614 +               case IPN_NODEFLAG_GRAB:
2615 +                       dev=dev_get_by_name(net,name);
2616 +                       if (dev) {
2617 +                               if (dev->flags & IFF_LOOPBACK)
2618 +                                       *err= -EINVAL;
2619 +                               else if (rcu_dereference(dev->ipn_port) != NULL)
2620 +                                       *err= -EBUSY;
2621 +                               if (*err)
2622 +                                       dev=NULL;
2623 +                       }
2624 +                       break;
2625 +       }
2626 +       return dev;
2629 +int ipn_netdev_activate(struct ipn_node *ipn_node)
2631 +       int rv=-EINVAL;
2632 +       switch (ipn_node->flags & IPN_NODEFLAG_DEVMASK) {
2633 +               case IPN_NODEFLAG_TAP:
2634 +                       {
2635 +                               struct ipntap *ipntap=netdev_priv(ipn_node->dev);
2636 +                               ipntap->ipn_node=ipn_node;
2637 +                               rtnl_lock(); 
2638 +                               if ((rv=register_netdevice(ipn_node->dev)) == 0)
2639 +                                       rcu_assign_pointer(ipn_node->dev->ipn_port, 
2640 +                                                       ipn_node);
2641 +                               rtnl_unlock();
2642 +                               if (rv) {/* error! */
2643 +                                       ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
2644 +                                       free_netdev(ipn_node->dev);
2645 +                               }
2646 +                       }
2647 +                       break;
2648 +               case IPN_NODEFLAG_GRAB:
2649 +                       rtnl_lock(); 
2650 +                       rcu_assign_pointer(ipn_node->dev->ipn_port, 
2651 +                                       ipn_node);
2652 +                       dev_set_promiscuity(ipn_node->dev,1);
2653 +                       rtnl_unlock();
2654 +                       rv=0;
2655 +                       break;
2656 +       }
2657 +       return rv;
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;
2665 +                       rtnl_lock(); 
2666 +                       rcu_assign_pointer(ipn_node->dev->ipn_port, NULL);
2667 +                       unregister_netdevice(ipn_node->dev);
2668 +                       rtnl_unlock();
2669 +                       free_netdev(ipn_node->dev);
2670 +                       break;
2671 +               case IPN_NODEFLAG_GRAB:
2672 +                       ipn_node->flags &= ~IPN_NODEFLAG_DEVMASK;
2673 +                       rtnl_lock(); 
2674 +                       rcu_assign_pointer(ipn_node->dev->ipn_port, NULL);
2675 +                       dev_set_promiscuity(ipn_node->dev,-1);
2676 +                       rtnl_unlock();
2677 +                       break;
2678 +       }
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);
2686 +       
2687 +       if (msg->len > dev->mtu)
2688 +               return;
2689 +       skb=alloc_skb(msg->len+NET_IP_ALIGN,GFP_KERNEL);
2690 +       if (!skb) {
2691 +               ipntap->stats.rx_dropped++;
2692 +               return;
2693 +       }
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);
2698 +                       netif_rx(skb);
2699 +                       ipntap->stats.rx_packets++;
2700 +                       ipntap->stats.rx_bytes += msg->len;
2701 +                       break;
2702 +               case IPN_NODEFLAG_GRAB:
2703 +                       skb->dev = dev;
2704 +                       dev_queue_xmit(skb);
2705 +                       break;
2706 +       }
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;
2723 +       return 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
2748 +               (void *)
2749 +#endif
2750 +               ipn_handle_hook;
2752 +       return 0;
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
2762 @@ -0,0 +1,56 @@
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) 
2769 + *
2770 + * Copyright (C) 2007   Renzo Davoli (renzo@cs.unibo.it)
2771 + *
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.
2776 + *
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.
2781 + *
2782 + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
2783 + *
2784 + */
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
2800 +#endif
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();
2818 +#endif