|
@@ -136,6 +136,7 @@
|
|
|
#include <linux/if_tunnel.h>
|
|
|
#include <linux/if_pppox.h>
|
|
|
#include <linux/ppp_defs.h>
|
|
|
+#include <linux/net_tstamp.h>
|
|
|
|
|
|
#include "net-sysfs.h"
|
|
|
|
|
@@ -1477,6 +1478,57 @@ static inline void net_timestamp_check(struct sk_buff *skb)
|
|
|
__net_timestamp(skb);
|
|
|
}
|
|
|
|
|
|
+static int net_hwtstamp_validate(struct ifreq *ifr)
|
|
|
+{
|
|
|
+ struct hwtstamp_config cfg;
|
|
|
+ enum hwtstamp_tx_types tx_type;
|
|
|
+ enum hwtstamp_rx_filters rx_filter;
|
|
|
+ int tx_type_valid = 0;
|
|
|
+ int rx_filter_valid = 0;
|
|
|
+
|
|
|
+ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ if (cfg.flags) /* reserved for future extensions */
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ tx_type = cfg.tx_type;
|
|
|
+ rx_filter = cfg.rx_filter;
|
|
|
+
|
|
|
+ switch (tx_type) {
|
|
|
+ case HWTSTAMP_TX_OFF:
|
|
|
+ case HWTSTAMP_TX_ON:
|
|
|
+ case HWTSTAMP_TX_ONESTEP_SYNC:
|
|
|
+ tx_type_valid = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (rx_filter) {
|
|
|
+ case HWTSTAMP_FILTER_NONE:
|
|
|
+ case HWTSTAMP_FILTER_ALL:
|
|
|
+ case HWTSTAMP_FILTER_SOME:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
|
|
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
|
|
+ rx_filter_valid = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!tx_type_valid || !rx_filter_valid)
|
|
|
+ return -ERANGE;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static inline bool is_skb_forwardable(struct net_device *dev,
|
|
|
struct sk_buff *skb)
|
|
|
{
|
|
@@ -4921,6 +4973,12 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
|
|
|
ifr->ifr_newname[IFNAMSIZ-1] = '\0';
|
|
|
return dev_change_name(dev, ifr->ifr_newname);
|
|
|
|
|
|
+ case SIOCSHWTSTAMP:
|
|
|
+ err = net_hwtstamp_validate(ifr);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+ /* fall through */
|
|
|
+
|
|
|
/*
|
|
|
* Unknown or private ioctl
|
|
|
*/
|