Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] UDPCP Communication Protocol
From: David Miller @ 2011-01-06 20:17 UTC (permalink / raw)
  To: pavel; +Cc: stefani, linux-kernel, akpm, netdev
In-Reply-To: <20110106201100.GA3582@ucw.cz>

From: Pavel Machek <pavel@ucw.cz>
Date: Thu, 6 Jan 2011 21:11:00 +0100

> Hi!
> 
>> UDPCP is a communication protocol specified by the Open Base Station
>> Architecture Initiative Special Interest Group (OBSAI SIG). The
>> protocol is based on UDP and is designed to meet the needs of "Mobile
>> Communcation Base Station" internal communications. It is widely used by
>> the major networks infrastructure supplier.
> 
> Why does it need to be in kernel?

To avoid a 40% performance hit which he explained in these threads.

^ permalink raw reply

* Re: [PATCH] UDPCP Communication Protocol
From: Pavel Machek @ 2011-01-06 20:11 UTC (permalink / raw)
  To: stefani; +Cc: linux-kernel, akpm, davem, netdev
In-Reply-To: <1293787785-3834-1-git-send-email-stefani@seibold.net>

Hi!

> UDPCP is a communication protocol specified by the Open Base Station
> Architecture Initiative Special Interest Group (OBSAI SIG). The
> protocol is based on UDP and is designed to meet the needs of "Mobile
> Communcation Base Station" internal communications. It is widely used by
> the major networks infrastructure supplier.

Why does it need to be in kernel?

> +struct udpcp_statistics {
> +	unsigned int txMsgs;		/* Num of transmitted messages */
> +	unsigned int rxMsgs;		/* Num of received messages */
> +	unsigned int txNodes;		/* Num of receiver nodes */
> +	unsigned int rxNodes;		/* Num of transmitter nodes */
> +	unsigned int txTimeout;		/* Num of unsuccessful transmissions */
> +	unsigned int rxTimeout;		/* Num of partial message receptions */
> +	unsigned int txRetries;		/* Num of resends */
> +	unsigned int rxDiscardedFrags;	/* Num of discarded fragments */
> +	unsigned int crcErrors;		/* Num of crc errors detected */
> +};
 
AvoidCamelCase.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* Re: [PATCH net-next-2.6 v3 1/1] can: c_can: Added support for Bosch C_CAN controller
From: Wolfgang Grandegger @ 2011-01-06 20:08 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, David Miller
In-Reply-To: <4D261BA4.2020003-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Hi Marc,

On 01/06/2011 08:44 PM, Marc Kleine-Budde wrote:
> Hello Wolfgang,
> 
> On 01/06/2011 08:40 PM, Wolfgang Grandegger wrote:
>> On 01/06/2011 08:33 PM, David Miller wrote:
>>> From: Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>
>>> Date: Tue, 4 Jan 2011 15:29:55 +0530
>>>
>>>> Bosch C_CAN controller is a full-CAN implementation which is compliant
>>>> to CAN protocol version 2.0 part A and B. Bosch C_CAN user manual can be
>>>> obtained from:
>>>> http://www.semiconductors.bosch.de/pdf/Users_Manual_C_CAN.pdf
>>>
>>> Can someone please review this driver submission?
>>
>> Yes, of course. I'm still on holiday, hope to find some time tomorrow.
> 
> If this driver will be merged, we'll have two drivers for the same can
> core in the tree. The other one is the pch_can. What do you think should
> be the mid term perspective for ccan based hardware?

Yes, I know. Unfortunately, we did realize rather late the the PCH
controller is a C_CAN clone and the OKI/Intel ppls did not tell us
either. Therefore I asked Bhupesh to provide a SJA1000-a-like interface
for the C_CAN, which would allow us to provide an alternative PCI driver
"pch_pci.c" for the PCH. If that driver works well on the PCH hardware
as well, we should merge the best of both, if necessary, and then
finally remove the pch_can driver. Would that be a reasonable proposal.

Wolfgang.

^ permalink raw reply

* Re: [PATCH V7 7/8] ptp: Added a clock driver for the IXP46x.
From: Pavel Machek @ 2011-01-06 20:04 UTC (permalink / raw)
  To: Richard Cochran
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	Alan Cox, Arnd Bergmann, Christoph Lameter, David Miller,
	John Stultz, Krzysztof Halasa, Peter Zijlstra, Rodolfo Giometti,
	Thomas Gleixner
In-Reply-To: <20110103170732.GA3700-7KxsofuKt4IfAd9E5cN8NEzG7cXyKsk/@public.gmane.org>

Hi!

> > Given the comments -- does manual really use camelCase crap?
> > And... the identifiers actually combine camelCase with _. Better fix
> > it.
> 
> Thats the way Intel likes it:
> 
> http://download.intel.com/design/network/manuals/30626204.pdf

Ok... I'd say that it is so ugly that it should be replaced, but it is
not huge deal.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* Re: [PATCH V8 09/13] posix clocks: introduce dynamic clocks
From: Arnd Bergmann @ 2011-01-06 19:56 UTC (permalink / raw)
  To: Richard Cochran
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
	Alan Cox, Christoph Lameter, David Miller, John Stultz,
	Krzysztof Halasa, Peter Zijlstra, Rodolfo Giometti,
	Thomas Gleixner
In-Reply-To: <c28004fc5d121c1dd5f842550663fc9d6f55a114.1293820862.git.richard.cochran-3mrvs1K0uXizZXS1Dc/lvw@public.gmane.org>

On Friday 31 December 2010, Richard Cochran wrote:
> This patch adds support for adding and removing posix clocks. The
> clock lifetime cycle is patterned after usb devices. Each clock is
> represented by a standard character device. In addition, the driver
> may optionally implemented custom character device operations.
> 
> The posix clock and timer system calls listed below now work with
> dynamic posix clocks, as well as the traditional static clocks.
> For the performance critical calls (eg clock_gettime) the code path
> from the traditional static clocks is preserved.

Combining the operations structures and using container_of as you did
looks much better than before, but I had something slightly different
in mind:

The way that other subsystems do this is to pass a pointer to the
actual low-level object (struct posix_clock in your case) to the
abstracted functions, while you pass a pointer to the operations
structure. This has the advantage of keeping the definition of
posix_clock private to posix-clock.c, but it is something we do
very rarely.

I can see disadvantages with your approach: You still need to dynamically
allocate the posix_clock in posix_clock_create(), and the operations
structure cannot be const, which is a theoretical security problem
if there is a hole that can replace one of the pointers with a
reference to user memory.

I would recommend changing this to the more common model, where you
passs the (publically defined) struct posix_clock to all operations
and can do something like:

struct my_posix_clock {
	...
	struct posix_clock pclk;
} this_clock = {
	...
	.pclk = {
		.ops = &my_posix_clock_operations,
	}
};

int my_init(void)
{
	return posix_clock_operations_register(&my_posix_clock.pclk);
}

void my_exit(void)
{
	posix_clock_operations_unregister(&my_posix_clock.pclk);
}

It should be just a trivial change and just affect how easy it is for
other people to understand the code if they are already familiar
with other kernel code.

Overall, your series looks really good now, it would be nice if this
could still make it into 2.6.38.

	Arnd

^ permalink raw reply

* Re: [PATCH 2/3] tlan: Fix partner capability printout
From: Ben Hutchings @ 2011-01-06 19:44 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: netdev
In-Reply-To: <4D2619BC.1030606@iki.fi>

On Thu, 2011-01-06 at 21:36 +0200, Sakari Ailus wrote:
> Ben Hutchings wrote:
> > On Thu, 2011-01-06 at 20:50 +0200, Sakari Ailus wrote:
> >> Fix partner capability printout. Add spaces and do not print null.
> >>
> >> Signed-off-by: Sakari Ailus<sakari.ailus@iki.fi>
> >> ---
> >>   drivers/net/tlan.c |    6 +++---
> >>   1 files changed, 3 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
> >> index 57380b1..090ce21 100644
> >> --- a/drivers/net/tlan.c
> >> +++ b/drivers/net/tlan.c
> >> @@ -2367,10 +2367,10 @@ tlan_finish_reset(struct net_device *dev)
> >>   					? "" : "0",
> >>   					tlphy_par&  TLAN_PHY_DUPLEX_FULL
> >>   					? "Full" : "half");
> >> -				pr_info("TLAN: Partner capability: ");
> >> -				for (i = 5; i<= 10; i++)
> >> +				pr_info("TLAN: Partner capability:");
> >> +				for (i = 5; i<  10; i++)
> >>   					if (partner&  (1<<i))
> >> -						printk("%s", media[i-5]);
> >> +						printk(" %s", media[i-5]);
> >>   				printk("\n");
> >>   			}
> >>
> >
> > Really you should remove this logging and report the information through
> > the ethtool interface.
> 
> Hi Ben,
> 
> Thanks for the comments.
> 
> The driver supports mii-tool but not ethtool. Do you think it'd be fine 
> to remove these prints with just mii-tool interface support?
> 
> I agree ethtool support would definitely make sense to have in tlan.

Assuming that tlan drives a fairly standard MDIO PHY, you should be able
to implement the PHY-related ethtool operations using
ethtool_op_get_link(), mii_nway_restart(), mii_ethtool_gset() and
mii_ethtool_sset().

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: [PATCH net-next-2.6 v3 1/1] can: c_can: Added support for Bosch C_CAN controller
From: Marc Kleine-Budde @ 2011-01-06 19:44 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, David Miller
In-Reply-To: <4D261AAA.5030005-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>


[-- Attachment #1.1: Type: text/plain, Size: 1105 bytes --]

Hello Wolfgang,

On 01/06/2011 08:40 PM, Wolfgang Grandegger wrote:
> On 01/06/2011 08:33 PM, David Miller wrote:
>> From: Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>
>> Date: Tue, 4 Jan 2011 15:29:55 +0530
>>
>>> Bosch C_CAN controller is a full-CAN implementation which is compliant
>>> to CAN protocol version 2.0 part A and B. Bosch C_CAN user manual can be
>>> obtained from:
>>> http://www.semiconductors.bosch.de/pdf/Users_Manual_C_CAN.pdf
>>
>> Can someone please review this driver submission?
> 
> Yes, of course. I'm still on holiday, hope to find some time tomorrow.

If this driver will be merged, we'll have two drivers for the same can
core in the tree. The other one is the pch_can. What do you think should
be the mid term perspective for ccan based hardware?

regards, Marc
-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

[-- Attachment #2: Type: text/plain, Size: 188 bytes --]

_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core

^ permalink raw reply

* Re: [PATCH] net: remove the duplicate #ifdef __KERNEL__
From: David Miller @ 2011-01-06 19:42 UTC (permalink / raw)
  To: xiaosuo; +Cc: shemminger, ebiederm, sjur.brandeland, xemul, linux-kernel,
	netdev
In-Reply-To: <1294300788-3540-1-git-send-email-xiaosuo@gmail.com>

From: Changli Gao <xiaosuo@gmail.com>
Date: Thu,  6 Jan 2011 15:59:48 +0800

> Since we are already in #ifdef __KERNEL__, we don't need to check it
> again.
> 
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>

Applied, but please CC: netdev on all networking patches.

> ---
>  include/linux/socket.h |    8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
> diff --git a/include/linux/socket.h b/include/linux/socket.h
> index 86b652f..5f65f14 100644
> --- a/include/linux/socket.h
> +++ b/include/linux/socket.h
> @@ -30,12 +30,10 @@ struct cred;
>  #define __sockaddr_check_size(size)	\
>  	BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage)))
>  
> -#ifdef __KERNEL__
> -# ifdef CONFIG_PROC_FS
> +#ifdef CONFIG_PROC_FS
>  struct seq_file;
>  extern void socket_seq_show(struct seq_file *seq);
> -# endif
> -#endif /* __KERNEL__ */
> +#endif
>  
>  typedef unsigned short	sa_family_t;
>  
> @@ -311,7 +309,6 @@ struct ucred {
>  /* IPX options */
>  #define IPX_TYPE	1
>  
> -#ifdef __KERNEL__
>  extern void cred_to_ucred(struct pid *pid, const struct cred *cred, struct ucred *ucred);
>  
>  extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
> @@ -333,6 +330,5 @@ struct timespec;
>  
>  extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
>  			  unsigned int flags, struct timespec *timeout);
> -#endif
>  #endif /* not kernel and not glibc */
>  #endif /* _LINUX_SOCKET_H */

^ permalink raw reply

* Re: [PATCH net-next-2.6 v3 1/1] can: c_can: Added support for Bosch C_CAN controller
From: Wolfgang Grandegger @ 2011-01-06 19:40 UTC (permalink / raw)
  To: David Miller
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20110106.113356.102556872.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>

On 01/06/2011 08:33 PM, David Miller wrote:
> From: Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>
> Date: Tue, 4 Jan 2011 15:29:55 +0530
> 
>> Bosch C_CAN controller is a full-CAN implementation which is compliant
>> to CAN protocol version 2.0 part A and B. Bosch C_CAN user manual can be
>> obtained from:
>> http://www.semiconductors.bosch.de/pdf/Users_Manual_C_CAN.pdf
> 
> Can someone please review this driver submission?

Yes, of course. I'm still on holiday, hope to find some time tomorrow.

Wolfgang.

^ permalink raw reply

* Re: [PATCH 2/3] tlan: Fix partner capability printout
From: Sakari Ailus @ 2011-01-06 19:36 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: netdev
In-Reply-To: <1294341774.11825.27.camel@bwh-desktop>

Ben Hutchings wrote:
> On Thu, 2011-01-06 at 20:50 +0200, Sakari Ailus wrote:
>> Fix partner capability printout. Add spaces and do not print null.
>>
>> Signed-off-by: Sakari Ailus<sakari.ailus@iki.fi>
>> ---
>>   drivers/net/tlan.c |    6 +++---
>>   1 files changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
>> index 57380b1..090ce21 100644
>> --- a/drivers/net/tlan.c
>> +++ b/drivers/net/tlan.c
>> @@ -2367,10 +2367,10 @@ tlan_finish_reset(struct net_device *dev)
>>   					? "" : "0",
>>   					tlphy_par&  TLAN_PHY_DUPLEX_FULL
>>   					? "Full" : "half");
>> -				pr_info("TLAN: Partner capability: ");
>> -				for (i = 5; i<= 10; i++)
>> +				pr_info("TLAN: Partner capability:");
>> +				for (i = 5; i<  10; i++)
>>   					if (partner&  (1<<i))
>> -						printk("%s", media[i-5]);
>> +						printk(" %s", media[i-5]);
>>   				printk("\n");
>>   			}
>>
>
> Really you should remove this logging and report the information through
> the ethtool interface.

Hi Ben,

Thanks for the comments.

The driver supports mii-tool but not ethtool. Do you think it'd be fine 
to remove these prints with just mii-tool interface support?

I agree ethtool support would definitely make sense to have in tlan.

Regards,

-- 
Sakari Ailus
sakari.ailus@iki.fi

^ permalink raw reply

* Re: pull request: wireless-next-2.6 2011-01-05
From: David Miller @ 2011-01-06 19:34 UTC (permalink / raw)
  To: linville-2XuSBdqkA4R54TAoqtyWWQ
  Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20110105215133.GA2369-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>

From: "John W. Linville" <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
Date: Wed, 5 Jan 2011 16:51:34 -0500

> Dave,
> 
> Here is another big batch of updates intended for 2.6.38.  It should
> be the last big one, but I still have a few patches in the queue that meet
> the posting date requirements and that might merit inclusion -- we'll
> see...
> 
> Again, this is the usual batch of driver updates from all the major
> players.  Also, mac80211 gets a little action.  The bluetooth team makes
> a showing as well.
> 
> Please let me know if there are problems!

Pulled, thanks John.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net-next-2.6 v3 1/1] can: c_can: Added support for Bosch C_CAN controller
From: David Miller @ 2011-01-06 19:33 UTC (permalink / raw)
  To: bhupesh.sharma-qxv4g6HH51o
  Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1294135195-9448-1-git-send-email-bhupesh.sharma-qxv4g6HH51o@public.gmane.org>

From: Bhupesh Sharma <bhupesh.sharma-qxv4g6HH51o@public.gmane.org>
Date: Tue, 4 Jan 2011 15:29:55 +0530

> Bosch C_CAN controller is a full-CAN implementation which is compliant
> to CAN protocol version 2.0 part A and B. Bosch C_CAN user manual can be
> obtained from:
> http://www.semiconductors.bosch.de/pdf/Users_Manual_C_CAN.pdf

Can someone please review this driver submission?

Thank you.

^ permalink raw reply

* Re: [PATCH] net: bridge: check the length of skb after nf_bridge_maybe_copy_header()
From: David Miller @ 2011-01-06 19:33 UTC (permalink / raw)
  To: xiaosuo; +Cc: shemminger, bridge, netdev
In-Reply-To: <AANLkTikb+o2tXg0uU92Q9foVqX2P49dhJX+umLX=Nhfn@mail.gmail.com>

From: Changli Gao <xiaosuo@gmail.com>
Date: Wed, 5 Jan 2011 21:37:28 +0800

> On Tue, Jan 4, 2011 at 4:13 AM, David Miller <davem@davemloft.net> wrote:
>> From: Stephen Hemminger <shemminger@linux-foundation.org>
>>>
>>> Because PPPOE happens afterwards and is not part the calculation.
>>> The check should be moved until after skb has reached final form.
>>
>> That works for me.
>>
> 
> So, is my patch acceptable?

Yes, I've applied it, thank you.

^ permalink raw reply

* Re: [PATCH 0/2] Re: spurious netconsole: network logging stopped messages
From: David Miller @ 2011-01-06 19:30 UTC (permalink / raw)
  To: wferi; +Cc: netdev
In-Reply-To: <cover.1294326001.git.wferi@niif.hu>

From: Ferenc Wagner <wferi@niif.hu>
Date: Thu,  6 Jan 2011 16:11:18 +0100

> Hi,
> 
> I've been running with these two patches for a couple of days now.
> I don't understand the bridge case: why should netconsole stop logging
> on a bridge device which lost a slave?  Or does NETDEV_BONDING_DESLAVE
> mean something else?
> 
> Anyway, I think the first patch fixes a real bug and the second makes
> the kernel message clearer, independently of its cause.

Both applied, thank you.

^ permalink raw reply

* Re: [PATCH net-next] cnic: Fix the type field in SPQ messages
From: David Miller @ 2011-01-06 19:27 UTC (permalink / raw)
  To: mchan; +Cc: netdev
In-Reply-To: <1294276453-5957-1-git-send-email-mchan@broadcom.com>

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 5 Jan 2011 17:14:13 -0800

> The new firmware interface requires each Slow Path Queue (SPQ) message's
> type field to include the function number.  The existing code does not
> do this consistently.  We fix this by OR'ing in the function number
> into the type field centrally in cnic_submit_kwqe_16().
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>

Applied, thank you.

^ permalink raw reply

* [RFC v2] ICMP sockets
From: Vasiliy Kulikov @ 2011-01-06 19:23 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel, David Miller, Solar Designer, Pavel Kankovsky

(David, please tell me whether it is acceptable as a whole)

This patch adds IPPROTO_ICMP socket kind.  It makes it possible to send
ICMP_ECHO messages and receive corresponding ICMP_ECHOREPLY messages
without any special privileges.  In other words, the patch makes it
possible to implement setuid-less /bin/ping.

A new ping socket is created with

    socket(PF_INET, SOCK_DGRAM, PROT_ICMP)

Message identifiers (octets 4-5 of ICMP header) are interpreted as local
ports. Addresses are stored in struct sockaddr_in. No port numbers are
reserved for privileged processes, port 0 is reserved for API ("let the
kernel pick a free number"). There is no notion of remote ports, remote
port numbers provided by the user (e.g. in connect()) are ignored.

Data sent and received include ICMP headers. This is deliberate to:
1) Avoid the need to transport headers values like sequence numbers by
other means
2) Make it easier to port existing programs using raw sockets.

ICMP headers given to send() are checked and sanitized. The type must be
ICMP_ECHO and the code must be zero (future extensions might relax this,
see below). The id is set to the number (local port) of the socket, the
checksum is always recomputed.

ICMP reply packets received from the network are demultiplexed according
to their id's and returned by recv() without any modifications.  IP
header information and ICMP errors of those packets may be obtained via
ancillary data (IP_RECVTTL, IP_RETOPTS, and IP_RECVERR). ICMP source
quenches and redirects are reported as fake errors via the error queue
(IP_RECVERR); the next hop address for redirects is saved to ee_info (in
network order).

Socket(2) is restricted to the group range specified in
"/proc/sys/net/ipv4/ping_group_range" (or the owner of CAP_NET_RAW).  It
is "1 0" by default, meaning that nobody except root may create ping
sockets.  Setting it to "100 100" would gain permissions to the single
group, "0 65535" would enable it for the world.

The existing code might be (in the unlikely case anyone needs it)
extended rather easily to handle other similar pairs of ICMP messages
(Timestamp/Reply, Information Request/Reply, Address Mask Request/Reply
etc.).


Userspace ping util & patch for it:
http://openwall.info/wiki/segoon/ping


Similar functionality is implemented in Mac OS X:
http://www.manpagez.com/man/4/icmp/


All ping options (-b, -p, -Q, -R, -s, -t, -T, -M, -I), are tested with
the patch.

Tested with 2K "ping -i0.2" running on Core i7 (8 cores), Load average =
80, and with 20 simultanious "ping -c1", each for an hour.  Namespace
functionality is tested with LXC.

Initially this functionality was written by Pavel Kankovsky (CC'ed him)
for linux 2.4.32, but unfortunately it was never made public.

Changes since v1:
    - minor cleanups.
    - introduced sysctl'able group range to restrict socket(2).

Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
Signed-off-by: Pavel Kankovsky <peak@argo.troja.mff.cuni.cz>
--
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index d68c3f1..ff3bb61 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -55,6 +55,8 @@ struct netns_ipv4 {
 	int sysctl_rt_cache_rebuild_count;
 	int current_rt_cache_rebuild_count;
 
+	unsigned int sysctl_ping_group_range[2];
+
 	atomic_t rt_genid;
 
 #ifdef CONFIG_IP_MROUTE
diff --git a/include/net/ping.h b/include/net/ping.h
new file mode 100644
index 0000000..3c35d4c
--- /dev/null
+++ b/include/net/ping.h
@@ -0,0 +1,73 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Definitions for the "ping" module.
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+#ifndef _PING_H
+#define _PING_H
+
+#include <net/netns/hash.h>
+
+#ifdef CONFIG_IP_PING_DEBUG
+#define ping_debug(fmt, x...) printk(KERN_INFO fmt, ## x)
+#else
+#define ping_debug(fmt, x...) do {} while (0)
+#endif
+
+/* PING_HTABLE_SIZE must be power of 2 */
+#define PING_HTABLE_SIZE 	64
+#define PING_HTABLE_MASK 	(PING_HTABLE_SIZE-1)
+
+#define ping_portaddr_for_each_entry(__sk, node, list) \
+	hlist_nulls_for_each_entry(__sk, node, list, sk_nulls_node)
+
+#define MAX_PING_IDENT 	65536
+
+
+struct ping_table {
+	struct hlist_nulls_head	hash[PING_HTABLE_SIZE];
+	rwlock_t		lock;
+};
+
+extern struct ping_table ping_table;
+
+struct ping_iter_state {
+	struct seq_net_private  p;
+	int			bucket;
+};
+
+extern struct proto ping_prot;
+
+
+#ifdef CONFIG_IP_PING
+#define icmp_echoreply ping_rcv
+#else
+#define icmp_echoreply icmp_discard
+#endif
+
+extern void ping_rcv(struct sk_buff *);
+extern void ping_err(struct sk_buff *, u32 info);
+
+//extern void inet_get_ping_group_range_net(struct net *net, unsigned int *low, unsigned int *high);
+extern void inet_get_ping_group_range_table(struct ctl_table *table, unsigned int *low, unsigned int *high);
+extern void set_ping_group_range(struct ctl_table *table, int range[2]);
+
+extern int __net_init ping_init_net(struct net *net);
+extern void __net_exit ping_exit_net(struct net *net);
+
+#ifdef CONFIG_PROC_FS
+extern int __init ping_proc_init(void);
+extern void ping_proc_exit(void);
+#endif
+
+void __init ping_init(void);
+
+
+#endif /* _PING_H */
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 9e95d7f..5cb13a3 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -14,6 +14,27 @@ config IP_MULTICAST
 	  <file:Documentation/networking/multicast.txt>. For most people, it's
 	  safe to say N.
 
+config IP_PING
+	bool "IP: ping socket"
+	depends on EXPERIMENTAL
+	help
+	  This option introduces a new kind of sockets - "ping sockets".
+
+	  A ping socket makes it possible to send ICMP Echo messages and receive
+	  corresponding ICMP Echo Reply messages without any special privileges.
+	  In other words, it makes is possible to implement setuid-less /bin/ping.
+
+	  A new ping socket is created with socket(PF_INET, SOCK_DGRAM, PROT_ICMP).
+
+config IP_PING_DEBUG
+	bool "IP: ping socket debug output"
+	depends on IP_PING
+	default n
+	help
+	  Enable the inclusion of debug code in the ICMP ping sockets.
+	  Be aware that doing this will impact performance.
+	  If unsure say N.
+
 config IP_ADVANCED_ROUTER
 	bool "IP: advanced router"
 	---help---
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 4978d22..975ef21 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
 obj-$(CONFIG_IP_MROUTE) += ipmr.o
+obj-$(CONFIG_IP_PING) += ping.o ping_proc.o
 obj-$(CONFIG_NET_IPIP) += ipip.o
 obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o
 obj-$(CONFIG_NET_IPGRE) += ip_gre.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index f581f77..bbe5eb3 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -105,6 +105,7 @@
 #include <net/tcp.h>
 #include <net/udp.h>
 #include <net/udplite.h>
+#include <net/ping.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/raw.h>
@@ -992,6 +993,16 @@ static struct inet_protosw inetsw_array[] =
 		.flags =      INET_PROTOSW_PERMANENT,
        },
 
+#ifdef CONFIG_IP_PING
+       {
+		.type =       SOCK_DGRAM,
+		.protocol =   IPPROTO_ICMP,
+		.prot =       &ping_prot,
+		.ops =        &inet_dgram_ops,
+		.no_check =   UDP_CSUM_DEFAULT,
+		.flags =      INET_PROTOSW_REUSE,
+       },
+#endif
 
        {
 	       .type =       SOCK_RAW,
@@ -1520,6 +1531,9 @@ static const struct net_protocol udp_protocol = {
 
 static const struct net_protocol icmp_protocol = {
 	.handler =	icmp_rcv,
+#ifdef CONFIG_IP_PING
+	.err_handler =	ping_err,
+#endif
 	.no_policy =	1,
 	.netns_ok =	1,
 };
@@ -1635,6 +1649,12 @@ static int __init inet_init(void)
 	if (rc)
 		goto out_unregister_udp_proto;
 
+#ifdef CONFIG_IP_PING
+	rc = proto_register(&ping_prot, 1);
+	if (rc)
+		goto out_unregister_raw_proto;
+#endif
+
 	/*
 	 *	Tell SOCKET that we are alive...
 	 */
@@ -1690,6 +1710,10 @@ static int __init inet_init(void)
 	/* Add UDP-Lite (RFC 3828) */
 	udplite4_register();
 
+#ifdef CONFIG_IP_PING
+	ping_init();
+#endif
+
 	/*
 	 *	Set the ICMP layer up
 	 */
@@ -1720,6 +1744,10 @@ static int __init inet_init(void)
 	rc = 0;
 out:
 	return rc;
+#ifdef CONFIG_IP_PING
+out_unregister_raw_proto:
+	proto_unregister(&raw_prot);
+#endif
 out_unregister_udp_proto:
 	proto_unregister(&udp_prot);
 out_unregister_tcp_proto:
@@ -1744,11 +1772,19 @@ static int __init ipv4_proc_init(void)
 		goto out_tcp;
 	if (udp4_proc_init())
 		goto out_udp;
+#ifdef CONFIG_IP_PING
+	if (ping_proc_init())
+		goto out_ping;
+#endif
 	if (ip_misc_proc_init())
 		goto out_misc;
 out:
 	return rc;
 out_misc:
+#ifdef CONFIG_IP_PING
+	ping_proc_exit();
+out_ping:
+#endif
 	udp4_proc_exit();
 out_udp:
 	tcp4_proc_exit();
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index e5d1a44..83232e2 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -83,6 +83,7 @@
 #include <net/tcp.h>
 #include <net/udp.h>
 #include <net/raw.h>
+#include <net/ping.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <linux/errno.h>
@@ -808,6 +809,17 @@ static void icmp_redirect(struct sk_buff *skb)
 			       iph->saddr, skb->dev);
 		break;
 	}
+
+#ifdef CONFIG_IP_PING
+	/* Ping wants to see redirects.
+         * Let's pretend they are errors of sorts... */
+	if (iph->protocol == IPPROTO_ICMP &&
+	    iph->ihl >= 5 &&
+	    pskb_may_pull(skb, (iph->ihl<<2)+8)) {
+		ping_err(skb, icmp_hdr(skb)->un.gateway);
+	}
+#endif
+
 out:
 	return;
 out_err:
@@ -1068,7 +1080,7 @@ error:
  */
 static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
 	[ICMP_ECHOREPLY] = {
-		.handler = icmp_discard,
+		.handler = icmp_echoreply,
 	},
 	[1] = {
 		.handler = icmp_discard,
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
new file mode 100644
index 0000000..9e1a7e9
--- /dev/null
+++ b/net/ipv4/ping.c
@@ -0,0 +1,787 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		"Ping" sockets
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Based on ipv4/udp.c code.
+ *
+ * Authors:	Vasiliy Kulikov / Openwall (for Linux 2.6),
+ *		Pavel Kankovsky (for Linux 2.4.32)
+ *
+ * Pavel gave all rights to bugs to Vasiliy,
+ * none of the bugs are Pavel's now.
+ *
+ */
+
+#include <asm/system.h>
+#include <linux/uaccess.h>
+#include <asm/ioctls.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <net/snmp.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/icmp.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/ping.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/route.h>
+#include <net/inet_common.h>
+#include <net/checksum.h>
+
+
+DEFINE_SEQLOCK(ping_group_range_lock);
+struct ping_table ping_table __read_mostly;
+
+u16 ping_port_rover;
+
+static inline int ping_hashfn(struct net *net, unsigned num, unsigned mask)
+{
+	int res = (num + net_hash_mix(net)) & mask;
+	ping_debug("hash(%d) = %d\n", num, res);
+	return res;
+}
+
+static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table,
+					     struct net *net, unsigned num)
+{
+	return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)];
+}
+
+void __inet_get_ping_group_range(unsigned *data, unsigned int *low, unsigned int *high)
+{
+	unsigned seq;
+	do {
+		seq = read_seqbegin(&ping_group_range_lock);
+
+		*low = data[0];
+		*high = data[1];
+	} while (read_seqretry(&ping_group_range_lock, seq));
+}
+
+void inet_get_ping_group_range_net(struct net *net, unsigned int *low, unsigned int *high)
+{
+	unsigned int *data = net->ipv4.sysctl_ping_group_range;
+	__inet_get_ping_group_range(data, low, high);
+}
+
+void inet_get_ping_group_range_table(struct ctl_table *table, unsigned int *low, unsigned int *high)
+{
+	unsigned int *data = table->data;
+	__inet_get_ping_group_range(data, low, high);
+}
+
+/* Update system visible IP port range */
+void set_ping_group_range(struct ctl_table *table, int range[2])
+{
+	int *data = table->data;
+	write_seqlock(&ping_group_range_lock);
+	data[0] = range[0];
+	data[1] = range[1];
+	write_sequnlock(&ping_group_range_lock);
+}
+
+static int ping_v4_get_port(struct sock *sk, unsigned short ident)
+{
+	struct hlist_nulls_node *node;
+	struct hlist_nulls_head *hlist;
+	struct inet_sock *isk, *isk2;
+	struct sock *sk2 = NULL;
+
+	isk = inet_sk(sk);
+	write_lock_bh(&ping_table.lock);
+	if (ident == 0) {
+		u32 i;
+		u16 result = ping_port_rover + 1;
+
+		for (i = 0; i < (1L << 16); i++, result++) {
+			if (!result)
+				result++; /* avoid zero */
+			hlist = ping_hashslot(&ping_table, sock_net(sk),
+					    result);
+			ping_portaddr_for_each_entry(sk2, node, hlist) {
+				isk2 = inet_sk(sk2);
+
+				if (isk2->inet_num == result)
+					goto next_port;
+			}
+
+			/* found */
+			ping_port_rover = ident = result;
+			break;
+next_port:
+			;
+		}
+		if (i >= (1L << 16))
+			goto fail;
+	} else {
+		hlist = ping_hashslot(&ping_table, sock_net(sk), ident);
+		ping_portaddr_for_each_entry(sk2, node, hlist) {
+			isk2 = inet_sk(sk2);
+
+			if ((isk2->inet_num == ident) &&
+			    (sk2 != sk) &&
+			    (!sk2->sk_reuse || !sk->sk_reuse))
+				goto fail;
+		}
+	}
+
+	ping_debug("found port/ident = %d\n", ident);
+	isk->inet_num = ident;
+	if (sk_unhashed(sk)) {
+		ping_debug("was not hashed\n");
+		sock_hold(sk);
+		hlist_nulls_add_head(&sk->sk_nulls_node, hlist);
+		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+	}
+	write_unlock_bh(&ping_table.lock);
+	return 0;
+
+fail:
+	write_unlock_bh(&ping_table.lock);
+	return 1;
+}
+
+static void ping_v4_hash(struct sock *sk)
+{
+	ping_debug("ping_v4_hash(sk->port=%u)\n", inet_sk(sk)->inet_num);
+	BUG(); /* "Please do not press this button again." */
+}
+
+static void ping_v4_unhash(struct sock *sk)
+{
+	struct inet_sock *isk = inet_sk(sk);
+	ping_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num);
+	if (sk_hashed(sk)) {
+		struct hlist_nulls_head *hslot;
+
+		hslot = ping_hashslot(&ping_table, sock_net(sk), isk->inet_num);
+		write_lock_bh(&ping_table.lock);
+		hlist_nulls_del(&sk->sk_nulls_node);
+		sock_put(sk);
+		isk->inet_num = isk->inet_sport = 0;
+		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+		write_unlock_bh(&ping_table.lock);
+	}
+}
+
+struct sock *ping_v4_lookup(struct net *net, u32 saddr, u32 daddr,
+	 u16 ident, int dif)
+{
+	struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident);
+	struct sock *sk = NULL;
+	struct inet_sock *isk;
+	struct hlist_nulls_node *hnode;
+
+	ping_debug("try to find: num = %d, daddr = %ld, dif = %d\n",
+			 (int)ident, (unsigned long)daddr, dif);
+	read_lock_bh(&ping_table.lock);
+
+	ping_portaddr_for_each_entry(sk, hnode, hslot) {
+		isk = inet_sk(sk);
+
+		ping_debug("found: %p: num = %d, daddr = %ld, dif = %d\n", sk,
+			 (int)isk->inet_num, (unsigned long)isk->inet_rcv_saddr,
+			 sk->sk_bound_dev_if);
+
+		ping_debug("iterate\n");
+		if (isk->inet_num != ident)
+			continue;
+		if (isk->inet_rcv_saddr && isk->inet_rcv_saddr != daddr)
+			continue;
+		if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
+			continue;
+
+		sock_hold(sk);
+		goto exit;
+	}
+
+	sk = NULL;
+exit:
+	read_unlock_bh(&ping_table.lock);
+
+	return sk;
+}
+
+static int ping_init_sock(struct sock *sk)
+{
+	struct net *net = sock_net(sk);
+	unsigned int group = current_egid(); /* XXX: maybe check all egroups? */
+	unsigned int range[2];
+
+	if (capable(CAP_NET_RAW))
+		return 0;
+
+	inet_get_ping_group_range_net(net, range, range+1);
+	if (range[0] <= group && group <= range[1])
+		return 0;
+
+	return -EACCES;
+}
+
+static void ping_close(struct sock *sk, long timeout)
+{
+	ping_debug("ping_close(sk=%p,sk->num=%u)\n",
+		inet_sk(sk), inet_sk(sk)->inet_num);
+	ping_debug("isk->refcnt = %d\n", sk->sk_refcnt.counter);
+
+	sk_common_release(sk);
+}
+
+/*
+ * We need our own bind because there are no privileged id's == local ports.
+ * Moreover, we don't allow binding to multi- and broadcast addresses.
+ */
+
+static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+	struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
+	struct inet_sock *isk = inet_sk(sk);
+	unsigned short snum;
+	int chk_addr_ret;
+	int err;
+
+	if (addr_len < sizeof(struct sockaddr_in))
+		return -EINVAL;
+
+	ping_debug("ping_v4_bind(sk=%p,sa_addr=%08x,sa_port=%d)\n",
+		sk, addr->sin_addr.s_addr, ntohs(addr->sin_port));
+
+	chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+	if (addr->sin_addr.s_addr == INADDR_ANY)
+		chk_addr_ret = RTN_LOCAL;
+
+	if ((sysctl_ip_nonlocal_bind == 0 &&
+	    isk->freebind == 0 && isk->transparent == 0 &&
+	     chk_addr_ret != RTN_LOCAL) ||
+	    chk_addr_ret == RTN_MULTICAST ||
+	    chk_addr_ret == RTN_BROADCAST)
+		return -EADDRNOTAVAIL;
+
+	lock_sock(sk);
+
+	err = -EINVAL;
+	if (isk->inet_num != 0)
+		goto out;
+
+	err = -EADDRINUSE;
+	isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr;
+	snum = ntohs(addr->sin_port);
+	if (ping_v4_get_port(sk, snum) != 0) {
+		isk->inet_saddr = isk->inet_rcv_saddr = 0;
+		goto out;
+	}
+
+	ping_debug("after bind(): num = %d, daddr = %ld, dif = %d\n",
+		(int)isk->inet_num,
+		(unsigned long) isk->inet_rcv_saddr,
+		(int)sk->sk_bound_dev_if);
+
+	err = 0;
+	if (isk->inet_rcv_saddr)
+		sk->sk_userlocks |= SOCK_BINDADDR_LOCK;
+	if (snum)
+		sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
+	isk->inet_sport = htons(isk->inet_num);
+	isk->inet_daddr = 0;
+	isk->inet_dport = 0;
+	sk_dst_reset(sk);
+out:
+	release_sock(sk);
+	ping_debug("ping_v4_bind -> %d\n", err);
+	return err;
+}
+
+/*
+ * Is this a supported type of ICMP message?
+ */
+
+static inline int ping_supported(int type, int code)
+{
+	if (type == ICMP_ECHO && code == 0)
+		return 1;
+	return 0;
+}
+
+/*
+ * This routine is called by the ICMP module when it gets some
+ * sort of error condition.
+ */
+
+static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
+
+void ping_err(struct sk_buff *skb, u32 info)
+{
+	struct iphdr *iph = (struct iphdr *)skb->data;
+	struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2));
+	struct inet_sock *inet_sock;
+	int type = icmph->type;
+	int code = icmph->code;
+	struct net *net = dev_net(skb->dev);
+	struct sock *sk;
+	int harderr;
+	int err;
+
+	/* We assume the packet has already been checked by icmp_unreach */
+
+	if (!ping_supported(icmph->type, icmph->code))
+		return;
+
+	ping_debug("ping_err(type=%04x,code=%04x,id=%04x,seq=%04x)\n", type,
+		code, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence));
+
+	sk = ping_v4_lookup(net, iph->daddr, iph->saddr,
+			    ntohs(icmph->un.echo.id), skb->dev->ifindex);
+	if (sk == NULL) {
+		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
+		ping_debug("no socket, dropping\n");
+		return;	/* No socket for error */
+	}
+	ping_debug("err on socket %p\n", sk);
+
+	err = 0;
+	harderr = 0;
+	inet_sock = inet_sk(sk);
+
+	switch (type) {
+	default:
+	case ICMP_TIME_EXCEEDED:
+		err = EHOSTUNREACH;
+		break;
+	case ICMP_SOURCE_QUENCH:
+		/* This is not a real error but ping wants to see it.
+		 * Report it with some fake errno. */
+		err = EREMOTEIO;
+		break;
+	case ICMP_PARAMETERPROB:
+		err = EPROTO;
+		harderr = 1;
+		break;
+	case ICMP_DEST_UNREACH:
+		if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */
+			if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) {
+				err = EMSGSIZE;
+				harderr = 1;
+				break;
+			}
+			goto out;
+		}
+		err = EHOSTUNREACH;
+		if (code <= NR_ICMP_UNREACH) {
+			harderr = icmp_err_convert[code].fatal;
+			err = icmp_err_convert[code].errno;
+		}
+		break;
+	case ICMP_REDIRECT:
+		/* See ICMP_SOURCE_QUENCH */
+		err = EREMOTEIO;
+		break;
+	}
+
+	/*
+	 *      RFC1122: OK.  Passes ICMP errors back to application, as per
+	 *	4.1.3.3.
+	 */
+	if (!inet_sock->recverr) {
+		if (!harderr || sk->sk_state != TCP_ESTABLISHED)
+			goto out;
+	} else {
+		ip_icmp_error(sk, skb, err, 0 /* no remote port */,
+			 info, (u8 *)icmph);
+	}
+	sk->sk_err = err;
+	sk->sk_error_report(sk);
+out:
+	sock_put(sk);
+}
+
+/*
+ *	Copy and checksum an ICMP Echo packet from user space into a buffer.
+ */
+
+struct pingfakehdr {
+	struct icmphdr icmph;
+	struct iovec *iov;
+	u32 wcheck;
+};
+
+static int ping_getfrag(void *from, char * to,
+			int offset, int fraglen, int odd, struct sk_buff *skb)
+{
+	struct pingfakehdr *pfh = (struct pingfakehdr *)from;
+
+	if (offset == 0) {
+		if (fraglen < sizeof(struct icmphdr))
+			BUG();
+		if (csum_partial_copy_fromiovecend(to + sizeof(struct icmphdr),
+			    pfh->iov, 0, fraglen - sizeof(struct icmphdr),
+			    &pfh->wcheck))
+			return -EFAULT;
+
+		pfh->wcheck = csum_partial((char *)&pfh->icmph,
+			sizeof(struct icmphdr), pfh->wcheck);
+		pfh->icmph.checksum = csum_fold(pfh->wcheck);
+		memcpy(to, &pfh->icmph, sizeof(struct icmphdr));
+		return 0;
+	}
+	if (offset < sizeof(struct icmphdr))
+		BUG();
+	if (csum_partial_copy_fromiovecend
+			(to, pfh->iov, offset - sizeof(struct icmphdr),
+			 fraglen, &pfh->wcheck))
+		return -EFAULT;
+	return 0;
+}
+
+int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+		 size_t len)
+{
+	struct inet_sock *isk = inet_sk(sk);
+	struct ipcm_cookie ipc;
+	struct icmphdr user_icmph;
+	struct pingfakehdr pfh;
+	struct rtable *rt = NULL;
+	int free = 0;
+	u32 saddr, daddr;
+	u8  tos;
+	int err;
+
+	ping_debug("ping_sendmsg(sk=%p,sk->num=%u)\n", isk, isk->inet_num);
+
+
+	if (len > 0xFFFF)
+		return -EMSGSIZE;
+
+	/*
+	 *	Check the flags.
+	 */
+
+	/* Mirror BSD error message compatibility */
+	if (msg->msg_flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	/*
+	 *	Fetch the ICMP header provided by the userland.
+	 *	iovec is modified!
+	 */
+
+	if (memcpy_fromiovec((u8 *)&user_icmph, msg->msg_iov,
+			     sizeof(struct icmphdr)))
+		return -EFAULT;
+	if (!ping_supported(user_icmph.type, user_icmph.code))
+		return -EINVAL;
+
+	/*
+	 *	Get and verify the address.
+	 */
+
+	if (msg->msg_name) {
+		struct sockaddr_in *usin = (struct sockaddr_in *)msg->msg_name;
+		if (msg->msg_namelen < sizeof(*usin))
+			return -EINVAL;
+		if (usin->sin_family != AF_INET)
+			return -EINVAL;
+		daddr = usin->sin_addr.s_addr;
+		/* no remote port */
+	} else {
+		if (sk->sk_state != TCP_ESTABLISHED)
+			return -EDESTADDRREQ;
+		daddr = isk->inet_daddr;
+		/* no remote port */
+	}
+
+	ipc.addr = isk->inet_saddr;
+	ipc.opt = NULL;
+	ipc.oif = sk->sk_bound_dev_if;
+
+	if (msg->msg_controllen) {
+		err = ip_cmsg_send(sock_net(sk), msg, &ipc);
+		if (err)
+			return err;
+		if (ipc.opt)
+			free = 1;
+	}
+	if (!ipc.opt)
+		ipc.opt = isk->opt;
+
+	saddr = ipc.addr;
+	ipc.addr = daddr;
+
+	if (ipc.opt && ipc.opt->srr) {
+		if (!daddr)
+			return -EINVAL;
+		daddr = ipc.opt->faddr;
+	}
+	tos = RT_TOS(isk->tos);
+	if (sock_flag(sk, SOCK_LOCALROUTE) ||
+	    (msg->msg_flags&MSG_DONTROUTE) ||
+	    (ipc.opt && ipc.opt->is_strictroute)) {
+		tos |= RTO_ONLINK;
+	}
+
+	if (ipv4_is_multicast(daddr)) {
+		if (!ipc.oif)
+			ipc.oif = isk->mc_index;
+		if (!saddr)
+			saddr = isk->mc_addr;
+	}
+
+	{
+		struct flowi fl = { .oif = ipc.oif,
+				    .mark = sk->sk_mark,
+				    .nl_u = { .ip4_u = {
+						.daddr = daddr,
+						.saddr = saddr,
+						.tos = tos } },
+				    .proto = IPPROTO_ICMP,
+				    .flags = inet_sk_flowi_flags(sk),
+		};
+
+		struct net *net = sock_net(sk);
+
+		security_sk_classify_flow(sk, &fl);
+		err = ip_route_output_flow(net, &rt, &fl, sk, 1);
+		if (err) {
+			if (err == -ENETUNREACH)
+				IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+			goto out;
+		}
+
+		err = -EACCES;
+		if ((rt->rt_flags & RTCF_BROADCAST) &&
+		    !sock_flag(sk, SOCK_BROADCAST))
+			goto out;
+	}
+
+	if (msg->msg_flags & MSG_CONFIRM)
+		goto do_confirm;
+back_from_confirm:
+
+	if (!ipc.addr)
+		ipc.addr = rt->rt_dst;
+
+	lock_sock(sk);
+
+	pfh.icmph.type = user_icmph.type; /* already checked */
+	pfh.icmph.code = user_icmph.code; /* dtto */
+	pfh.icmph.checksum = 0;
+	pfh.icmph.un.echo.id = isk->inet_sport;
+	pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence;
+	pfh.iov = msg->msg_iov;
+	pfh.wcheck = 0;
+
+	err = ip_append_data(sk, ping_getfrag, &pfh, len,
+			0, &ipc, &rt,
+			msg->msg_flags);
+	if (err)
+		ip_flush_pending_frames(sk);
+	else
+		err = ip_push_pending_frames(sk);
+	release_sock(sk);
+
+out:
+	ip_rt_put(rt);
+	if (free)
+		kfree(ipc.opt);
+	if (!err) {
+		icmp_out_count(sock_net(sk), user_icmph.type);
+		return len;
+	}
+	return err;
+
+do_confirm:
+	dst_confirm(&rt->dst);
+	if (!(msg->msg_flags & MSG_PROBE) || len)
+		goto back_from_confirm;
+	err = 0;
+	goto out;
+}
+
+/*
+ *	IOCTL requests applicable to the UDP^H^H^HICMP protocol
+ */
+
+int ping_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+	ping_debug("ping_ioctl(sk=%p,sk->num=%u,cmd=%d,arg=%lu)\n",
+		inet_sk(sk), inet_sk(sk)->inet_num, cmd, arg);
+	switch (cmd) {
+	case SIOCOUTQ:
+	case SIOCINQ:
+		return udp_ioctl(sk, cmd, arg);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+		 size_t len, int noblock, int flags, int *addr_len)
+{
+	struct inet_sock *isk = inet_sk(sk);
+	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
+	struct sk_buff *skb;
+	int copied, err;
+
+	ping_debug("ping_recvmsg(sk=%p,sk->num=%u)\n", isk, isk->inet_num);
+
+	if (flags & MSG_OOB)
+		goto out;
+
+	if (addr_len)
+		*addr_len = sizeof(*sin);
+
+	if (flags & MSG_ERRQUEUE)
+		return ip_recv_error(sk, msg, len);
+
+	skb = skb_recv_datagram(sk, flags, noblock, &err);
+	if (!skb)
+		goto out;
+
+	copied = skb->len;
+	if (copied > len) {
+		msg->msg_flags |= MSG_TRUNC;
+		copied = len;
+	}
+
+	/* Don't bother checking the checksum */
+	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+	if (err)
+		goto done;
+
+	sock_recv_timestamp(msg, sk, skb);
+
+	/* Copy the address. */
+	if (sin) {
+		sin->sin_family = AF_INET;
+		sin->sin_port = 0 /* skb->h.uh->source */;
+		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
+		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+	}
+	if (isk->cmsg_flags)
+		ip_cmsg_recv(msg, skb);
+	err = copied;
+
+done:
+	skb_free_datagram(sk, skb);
+out:
+	ping_debug("ping_recvmsg -> %d\n", err);
+	return err;
+}
+
+static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+	ping_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n",
+		inet_sk(sk), inet_sk(sk)->inet_num, skb);
+	if (sock_queue_rcv_skb(sk, skb) < 0) {
+		ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_INERRORS);
+		kfree_skb(skb);
+		ping_debug("ping_queue_rcv_skb -> failed\n");
+		return -1;
+	}
+	return 0;
+}
+
+
+/*
+ *	All we need to do is get the socket.
+ */
+
+void ping_rcv(struct sk_buff *skb)
+{
+	struct sock *sk;
+	struct net *net = dev_net(skb->dev);
+	struct iphdr *iph = ip_hdr(skb);
+	struct icmphdr *icmph = icmp_hdr(skb);
+	u32 saddr = iph->saddr;
+	u32 daddr = iph->daddr;
+
+	/* We assume the packet has already been checked by icmp_rcv */
+
+	ping_debug("ping_rcv(skb=%p,id=%04x,seq=%04x)\n",
+		skb, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence));
+
+	/* Push ICMP header back */
+	skb_push(skb, skb->data - (u8 *)icmph);
+
+	sk = ping_v4_lookup(net, saddr, daddr, ntohs(icmph->un.echo.id),
+			    skb->dev->ifindex);
+	if (sk != NULL) {
+		ping_debug("rcv on socket %p\n", sk);
+		ping_queue_rcv_skb(sk, skb_get(skb));
+		sock_put(sk);
+		return;
+	}
+	ping_debug("no socket, dropping\n");
+
+	/* We're called from icmp_rcv(). kfree_skb() is done there. */
+}
+
+struct proto ping_prot = {
+	.name =		"PING",
+	.owner =	THIS_MODULE,
+	.init =		ping_init_sock,
+	.close =	ping_close,
+	.connect =	ip4_datagram_connect,
+	.disconnect =	udp_disconnect,
+	.ioctl =	ping_ioctl,
+	.setsockopt =	ip_setsockopt,
+	.getsockopt =	ip_getsockopt,
+	.sendmsg =	ping_sendmsg,
+	.recvmsg =	ping_recvmsg,
+	.bind =		ping_bind,
+	.backlog_rcv =	ping_queue_rcv_skb,
+	.hash =		ping_v4_hash,
+	.unhash =	ping_v4_unhash,
+	.get_port =	ping_v4_get_port,
+	.obj_size =	sizeof(struct inet_sock),
+};
+EXPORT_SYMBOL(ping_prot);
+
+
+
+#ifdef CONFIG_PROC_FS
+
+static struct pernet_operations ping_net_ops = {
+	.init = ping_init_net,
+	.exit = ping_exit_net,
+};
+
+int __init ping_proc_init(void)
+{
+	return register_pernet_subsys(&ping_net_ops);
+}
+
+void ping_proc_exit(void)
+{
+	unregister_pernet_subsys(&ping_net_ops);
+}
+
+#endif
+
+void __init ping_init(void)
+{
+	int i;
+
+	for (i = 0; i < PING_HTABLE_SIZE; i++)
+		INIT_HLIST_NULLS_HEAD(&ping_table.hash[i], i);
+	rwlock_init(&ping_table.lock);
+}
diff --git a/net/ipv4/ping_proc.c b/net/ipv4/ping_proc.c
new file mode 100644
index 0000000..c13af0d
--- /dev/null
+++ b/net/ipv4/ping_proc.c
@@ -0,0 +1,216 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		"Ping" sockets
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Based on ipv4/udp.c code.
+ *
+ * Authors:	Vasiliy Kulikov / Openwall (for Linux 2.6),
+ *		Pavel Kankovsky (for Linux 2.4.32)
+ *
+ * Pavel gave all rights to bugs to Vasiliy,
+ * none of the bugs are Pavel's now.
+ *
+ */
+
+#include <asm/system.h>
+#include <linux/uaccess.h>
+#include <asm/ioctls.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <net/snmp.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/icmp.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/ping.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/route.h>
+#include <net/inet_common.h>
+#include <net/checksum.h>
+
+#ifdef CONFIG_PROC_FS
+
+static void ping_format_sock(struct sock *sp, struct seq_file *f,
+		int bucket, int *len)
+{
+	struct inet_sock *inet = inet_sk(sp);
+	__be32 dest = inet->inet_daddr;
+	__be32 src = inet->inet_rcv_saddr;
+	__u16 destp = ntohs(inet->inet_dport);
+	__u16 srcp = ntohs(inet->inet_sport);
+
+	seq_printf(f, "%5d: %08X:%04X %08X:%04X"
+		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d%n",
+		bucket, src, srcp, dest, destp, sp->sk_state,
+		sk_wmem_alloc_get(sp),
+		sk_rmem_alloc_get(sp),
+		0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
+		atomic_read(&sp->sk_refcnt), sp,
+		atomic_read(&sp->sk_drops), len);
+}
+
+static struct sock *ping_get_first(struct seq_file *seq, int start)
+{
+	struct sock *sk;
+	struct ping_iter_state *state = seq->private;
+	struct net *net = seq_file_net(seq);
+
+	for (state->bucket = start; state->bucket < PING_HTABLE_SIZE;
+	     ++state->bucket) {
+		struct hlist_nulls_node *node;
+		struct hlist_nulls_head *hslot = &ping_table.hash[state->bucket];
+
+		if (hlist_nulls_empty(hslot))
+			continue;
+
+		sk_nulls_for_each(sk, node, hslot) {
+			if (net_eq(sock_net(sk), net))
+				goto found;
+		}
+	}
+	sk = NULL;
+found:
+	return sk;
+}
+
+static struct sock *ping_get_next(struct seq_file *seq, struct sock *sk)
+{
+	struct ping_iter_state *state = seq->private;
+	struct net *net = seq_file_net(seq);
+
+	do {
+		sk = sk_nulls_next(sk);
+	} while (sk && (!net_eq(sock_net(sk), net)));
+
+	if (!sk)
+		return ping_get_first(seq, state->bucket + 1);
+	return sk;
+}
+
+static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct sock *sk = ping_get_first(seq, 0);
+
+	if (sk)
+		while (pos && (sk = ping_get_next(seq, sk)) != NULL)
+			--pos;
+	return pos ? NULL : sk;
+}
+
+static void *ping_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	struct ping_iter_state *state = seq->private;
+	state->bucket = 0;
+
+	read_lock_bh(&ping_table.lock);
+
+	return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN;
+}
+
+static void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct sock *sk;
+
+	if (v == SEQ_START_TOKEN)
+		sk = ping_get_idx(seq, 0);
+	else
+		sk = ping_get_next(seq, v);
+
+	++*pos;
+	return sk;
+}
+
+static void ping_seq_stop(struct seq_file *seq, void *v)
+{
+	read_unlock_bh(&ping_table.lock);
+}
+
+static int ping_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == SEQ_START_TOKEN)
+		seq_printf(seq, "%-127s\n",
+			   "  sl  local_address rem_address   st tx_queue "
+			   "rx_queue tr tm->when retrnsmt   uid  timeout "
+			   "inode ref pointer drops");
+	else {
+		struct ping_iter_state *state = seq->private;
+		int len;
+
+		ping_format_sock(v, seq, state->bucket, &len);
+		seq_printf(seq, "%*s\n", 127 - len, "");
+	}
+	return 0;
+}
+
+static const struct seq_operations ping_seq_ops = {
+	.show		= ping_seq_show,
+	.start		= ping_seq_start,
+	.next		= ping_seq_next,
+	.stop		= ping_seq_stop,
+};
+
+static int ping_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open_net(inode, file, &ping_seq_ops,
+			   sizeof(struct ping_iter_state));
+}
+
+static const struct file_operations ping_seq_fops = {
+	.owner		= THIS_MODULE,
+	.open		= ping_seq_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release_net,
+};
+
+static const char ping_proc_name[] = "icmp";
+
+static int ping_proc_register(struct net *net)
+{
+	struct proc_dir_entry *p;
+	int rc = 0;
+
+	p = proc_create_data(ping_proc_name, S_IRUGO, net->proc_net,
+			     &ping_seq_fops, NULL);
+	if (!p)
+		rc = -ENOMEM;
+	return rc;
+}
+
+static void ping_proc_unregister(struct net *net)
+{
+	proc_net_remove(net, ping_proc_name);
+}
+
+
+int __net_init ping_init_net(struct net *net)
+{
+	return ping_proc_register(net);
+}
+
+void __net_exit ping_exit_net(struct net *net)
+{
+	ping_proc_unregister(net);
+}
+
+#endif
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 1b4ec21..adf9de0 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -13,6 +13,7 @@
 #include <linux/seqlock.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/nsproxy.h>
 #include <net/snmp.h>
 #include <net/icmp.h>
 #include <net/ip.h>
@@ -21,11 +22,15 @@
 #include <net/udp.h>
 #include <net/cipso_ipv4.h>
 #include <net/inet_frag.h>
+#include <net/ping.h>
 
 static int zero;
 static int tcp_retr1_max = 255;
 static int ip_local_port_range_min[] = { 1, 1 };
 static int ip_local_port_range_max[] = { 65535, 65535 };
+static int ip_ping_group_range_min[] = { 0, 0 };
+static int ip_ping_group_range_max[] = { 65535, 65535 };
+static const int ip_ping_group_range_default[] = { 1, 0};
 static int tcp_adv_win_scale_min = -31;
 static int tcp_adv_win_scale_max = 31;
 
@@ -66,6 +71,32 @@ static int ipv4_local_port_range(ctl_table *table, int write,
 	return ret;
 }
 
+/* Validate changes from /proc interface. */
+static int ipv4_ping_group_range(ctl_table *table, int write,
+				 void __user *buffer,
+				 size_t *lenp, loff_t *ppos)
+{
+	int ret;
+	int range[2];
+	ctl_table tmp = {
+		.data = &range,
+		.maxlen = sizeof(range),
+		.mode = table->mode,
+		.extra1 = &ip_ping_group_range_min,
+		.extra2 = &ip_ping_group_range_max,
+	};
+
+	inet_get_ping_group_range_table(table, range, range + 1);
+	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+
+	if (write && ret == 0)
+		set_ping_group_range(table, range);
+
+	return ret;
+}
+
+
+
 static int proc_tcp_congestion_control(ctl_table *ctl, int write,
 				       void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -677,6 +708,15 @@ static struct ctl_table ipv4_net_table[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
+#ifdef CONFIG_IP_PING
+	{
+		.procname	= "ping_group_range",
+		.data		= &init_net.ipv4.sysctl_ping_group_range,
+		.maxlen		= sizeof(init_net.ipv4.sysctl_ping_group_range),
+		.mode		= 0644,
+		.proc_handler	= ipv4_ping_group_range,
+	},
+#endif
 	{ }
 };
 
@@ -711,8 +751,22 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
 			&net->ipv4.sysctl_icmp_ratemask;
 		table[6].data =
 			&net->ipv4.sysctl_rt_cache_rebuild_count;
+#ifdef CONFIG_IP_PING
+		table[7].data =
+			&net->ipv4.sysctl_ping_group_range;
+#endif
+
 	}
 
+#ifdef CONFIG_IP_PING
+	/*
+	 * Sane defaults - only processes with CAP_NET_RAW
+	 * may create ping sockets.
+	 */
+	net->ipv4.sysctl_ping_group_range[0] = ip_ping_group_range_default[0];
+	net->ipv4.sysctl_ping_group_range[1] = ip_ping_group_range_default[1];
+#endif
+
 	net->ipv4.sysctl_rt_cache_rebuild_count = 4;
 
 	net->ipv4.ipv4_hdr = register_net_sysctl_table(net,
--

^ permalink raw reply related

* Re: [PATCH 2/3] tlan: Fix partner capability printout
From: Ben Hutchings @ 2011-01-06 19:22 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: netdev
In-Reply-To: <1294339817-31434-2-git-send-email-sakari.ailus@iki.fi>

On Thu, 2011-01-06 at 20:50 +0200, Sakari Ailus wrote:
> Fix partner capability printout. Add spaces and do not print null.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
> ---
>  drivers/net/tlan.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
> index 57380b1..090ce21 100644
> --- a/drivers/net/tlan.c
> +++ b/drivers/net/tlan.c
> @@ -2367,10 +2367,10 @@ tlan_finish_reset(struct net_device *dev)
>  					? "" : "0",
>  					tlphy_par & TLAN_PHY_DUPLEX_FULL
>  					? "Full" : "half");
> -				pr_info("TLAN: Partner capability: ");
> -				for (i = 5; i <= 10; i++)
> +				pr_info("TLAN: Partner capability:");
> +				for (i = 5; i < 10; i++)
>  					if (partner & (1<<i))
> -						printk("%s", media[i-5]);
> +						printk(" %s", media[i-5]);
>  				printk("\n");
>  			}
>  

Really you should remove this logging and report the information through
the ethtool interface.

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* Re: [PATCH v2] netfilter: fix the race when initializing nf_ct_expect_hash_rnd
From: David Miller @ 2011-01-06 19:22 UTC (permalink / raw)
  To: eric.dumazet; +Cc: xiaosuo, kaber, netfilter-devel, netdev
In-Reply-To: <1294250598.10633.77.camel@edumazet-laptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 05 Jan 2011 19:03:18 +0100

> Le mercredi 05 janvier 2011 à 22:23 +0800, Changli Gao a écrit :
>> Since nf_ct_expect_dst_hash() may be called without nf_conntrack_lock
>> locked, nf_ct_expect_hash_rnd should be initialized in the atomic way.
>> 
>> In this patch, we use nf_conntrack_hash_rnd instead of
>> nf_ct_expect_hash_rnd.
>> 
>> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
>> ---
> 
> Acked-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH] ipv4: IP defragmentation must be ECN aware
From: David Miller @ 2011-01-06 19:21 UTC (permalink / raw)
  To: eric.dumazet; +Cc: shemminger, netdev
In-Reply-To: <1294249975.10633.74.camel@edumazet-laptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 05 Jan 2011 18:52:55 +0100

> [PATCH v2] ipv4: IP defragmentation must be ECN aware
> 
> RFC3168 (The Addition of Explicit Congestion Notification to IP)
> states :
> 
> 5.3.  Fragmentation
> 
>    ECN-capable packets MAY have the DF (Don't Fragment) bit set.
>    Reassembly of a fragmented packet MUST NOT lose indications of
>    congestion.  In other words, if any fragment of an IP packet to be
>    reassembled has the CE codepoint set, then one of two actions MUST be
>    taken:
> 
>       * Set the CE codepoint on the reassembled packet.  However, this
>         MUST NOT occur if any of the other fragments contributing to
>         this reassembly carries the Not-ECT codepoint.
> 
>       * The packet is dropped, instead of being reassembled, for any
>         other reason.
> 
> This patch implements this requirement for IPv4, choosing the first
> action : 
> 
> If one fragment had NO-ECT codepoint
>         reassembled frame has NO-ECT
> ElIf one fragment had CE codepoint
>         reassembled frame has CE
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied, thanks a lot Eric.

^ permalink raw reply

* Re: [PATCH] net: r6040: Return proper error for r6040_init_one
From: David Miller @ 2011-01-06 19:18 UTC (permalink / raw)
  To: florian; +Cc: axel.lin, linux-kernel, netdev
In-Reply-To: <201101051050.45381.florian@openwrt.org>

From: Florian Fainelli <florian@openwrt.org>
Date: Wed, 5 Jan 2011 10:50:45 +0100

> On Wednesday 05 January 2011 09:40:04 Axel Lin wrote:
>> Return -ENOMEM instead of 0 for the case of mdiobus_alloc and kmalloc
>> failure.
>>
>> Signed-off-by: Axel Lin <axel.lin@gmail.com>
> 
> Acked-by: Florian Fainelli <florian@openwrt.org>

Applied, thanks.

^ permalink raw reply

* Re: [patch 2/2] dcb: use after free in dcb_flushapp()
From: David Miller @ 2011-01-06 19:17 UTC (permalink / raw)
  To: error27; +Cc: netdev, john.r.fastabend, shmulikr, kernel-janitors
In-Reply-To: <20110105070344.GB24847@bicker>

From: Dan Carpenter <error27@gmail.com>
Date: Wed, 5 Jan 2011 10:03:44 +0300

> The original code has a use after free bug because it's not using the
> _safe() version of the list_for_each_entry() macro.
> 
> Signed-off-by: Dan Carpenter <error27@gmail.com>

Also applied.

^ permalink raw reply

* Re: [patch 1/2] dcb: unlock on error in dcbnl_ieee_get()
From: David Miller @ 2011-01-06 19:17 UTC (permalink / raw)
  To: error27; +Cc: netdev, john.r.fastabend, shmulikr, kernel-janitors
In-Reply-To: <20110105070312.GA24847@bicker>

From: Dan Carpenter <error27@gmail.com>
Date: Wed, 5 Jan 2011 10:03:12 +0300

> There is a "goto nla_put_failure" hidden inside the NLA_PUT() macro, but
> we're holding the dcb_lock so we need to unlock first.
> 
> Signed-off-by: Dan Carpenter <error27@gmail.com>

Applied, thanks Dan.

^ permalink raw reply

* Re: [PATCH] net: ixp4xx_eth: Return proper error for eth_init_one
From: David Miller @ 2011-01-06 19:11 UTC (permalink / raw)
  To: khc; +Cc: axel.lin, linux-kernel, netdev
In-Reply-To: <m3bp3vi6v9.fsf@intrepid.localdomain>

From: Krzysztof Halasa <khc@pm.waw.pl>
Date: Wed, 05 Jan 2011 18:43:22 +0100

> Axel Lin <axel.lin@gmail.com> writes:
> 
>> Return PTR_ERR(port->phydev) instead of 1 if phy_connect failed.
>>
>> Signed-off-by: Axel Lin <axel.lin@gmail.com>
> 
>> --- a/drivers/net/arm/ixp4xx_eth.c
>> +++ b/drivers/net/arm/ixp4xx_eth.c
>> @@ -1229,8 +1229,10 @@ static int __devinit eth_init_one(struct platform_device *pdev)
>>  	snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, "0", plat->phy);
>>  	port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
>>  				   PHY_INTERFACE_MODE_MII);
>> -	if ((err = IS_ERR(port->phydev)))
>> +	if (IS_ERR(port->phydev)) {
>> +		err = PTR_ERR(port->phydev);
>>  		goto err_free_mem;
>> +	}
>>  
>>  	port->phydev->irq = PHY_POLL;
> 
> Right. Thanks.
> 
> Acked-by: Krzysztof Halasa <khc@pm.waw.pl>

I'll apply this, thanks.

^ permalink raw reply

* Re: [PATCH] include/linux/if_ether.h: Add #define ETH_P_LINK_CTL for HPNA and wlan local tunnel
From: David Miller @ 2011-01-06 19:10 UTC (permalink / raw)
  To: henryp; +Cc: joe, brudley, arend, rvossen, dowan, netdev
In-Reply-To: <1294193234-804-1-git-send-email-henryp@broadcom.com>

From: "Henry Ptasinski" <henryp@broadcom.com>
Date: Tue, 4 Jan 2011 18:07:14 -0800

> Ethertype used by HPNA control protocols (LARQ, rate, link, etc) and by
> Broadcom wlan drivers for local signalling.
> 
> Signed-off-by: Henry Ptasinski <henryp@broadcom.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] net: ppp: use {get,put}_unaligned_be{16,32}
From: Harvey Harrison @ 2011-01-06 19:07 UTC (permalink / raw)
  To: Changli Gao; +Cc: David S. Miller, Paul Mackerras, linux-ppp, netdev
In-Reply-To: <1294306655-22033-1-git-send-email-xiaosuo@gmail.com>

On Thu, Jan 6, 2011 at 1:37 AM, Changli Gao <xiaosuo@gmail.com> wrote:
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
> ---
>  drivers/net/ppp_async.c   |   10 +++++-----
>  drivers/net/ppp_deflate.c |    9 ++++-----
>  drivers/net/ppp_generic.c |    9 ++++-----
>  drivers/net/ppp_mppe.c    |    7 +++----
>  drivers/net/ppp_synctty.c |    3 ++-
>  5 files changed, 18 insertions(+), 20 deletions(-)
> diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
> index 78d70a6..cbe1e13 100644
> --- a/drivers/net/ppp_async.c
> +++ b/drivers/net/ppp_async.c
> @@ -32,6 +32,7 @@
>  #include <linux/init.h>
>  #include <linux/jiffies.h>
>  #include <linux/slab.h>
> +#include <linux/unaligned/be_struct.h>

#include <asm/unaligned.h>

Same for the other occurances, otherwise looks OK.

Harvey

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox