Commit 6c951b90 authored by Frank Pavlic's avatar Frank Pavlic Committed by Jeff Garzik

[PATCH] s390: introduce guestLan sniffer support in qeth

[patch 6/7] s390: introduce guestLan sniffer support in qeth

From: Peter Tiedemann  <ptiedem@de.ibm.com>
	- introduce guestLan sniffer support in qeth
	  feature allows a linux in a virtual machine
	  guest to become a network LAN sniffer,
	  monitoring and recording the networking traffic
	  within an entire guestLan.
Signed-off-by: default avatarFrank Pavlic <fpavlic@de.ibm.com>

diffstat:
 qeth.h      |    2 +
 qeth_main.c |   93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qeth_mpc.h  |   11 ++++---
 3 files changed, 102 insertions(+), 4 deletions(-)
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent e08d88cc
...@@ -750,6 +750,7 @@ struct qeth_card_info { ...@@ -750,6 +750,7 @@ struct qeth_card_info {
int unique_id; int unique_id;
struct qeth_card_blkt blkt; struct qeth_card_blkt blkt;
__u32 csum_mask; __u32 csum_mask;
enum qeth_ipa_promisc_modes promisc_mode;
}; };
struct qeth_card_options { struct qeth_card_options {
...@@ -776,6 +777,7 @@ struct qeth_card_options { ...@@ -776,6 +777,7 @@ struct qeth_card_options {
enum qeth_threads { enum qeth_threads {
QETH_SET_IP_THREAD = 1, QETH_SET_IP_THREAD = 1,
QETH_RECOVER_THREAD = 2, QETH_RECOVER_THREAD = 2,
QETH_SET_PROMISC_MODE_THREAD = 4,
}; };
struct qeth_osn_info { struct qeth_osn_info {
......
...@@ -159,6 +159,9 @@ qeth_get_addr_buffer(enum qeth_prot_versions); ...@@ -159,6 +159,9 @@ qeth_get_addr_buffer(enum qeth_prot_versions);
static void static void
qeth_set_multicast_list(struct net_device *); qeth_set_multicast_list(struct net_device *);
static void
qeth_setadp_promisc_mode(struct qeth_card *);
static void static void
qeth_notify_processes(void) qeth_notify_processes(void)
{ {
...@@ -965,6 +968,24 @@ qeth_register_ip_addresses(void *ptr) ...@@ -965,6 +968,24 @@ qeth_register_ip_addresses(void *ptr)
return 0; return 0;
} }
/*
* Drive the SET_PROMISC_MODE thread
*/
static int
qeth_set_promisc_mode(void *ptr)
{
struct qeth_card *card = (struct qeth_card *) ptr;
daemonize("qeth_setprm");
QETH_DBF_TEXT(trace,4,"setprm1");
if (!qeth_do_run_thread(card, QETH_SET_PROMISC_MODE_THREAD))
return 0;
QETH_DBF_TEXT(trace,4,"setprm2");
qeth_setadp_promisc_mode(card);
qeth_clear_thread_running_bit(card, QETH_SET_PROMISC_MODE_THREAD);
return 0;
}
static int static int
qeth_recover(void *ptr) qeth_recover(void *ptr)
{ {
...@@ -1031,6 +1052,8 @@ qeth_start_kernel_thread(struct qeth_card *card) ...@@ -1031,6 +1052,8 @@ qeth_start_kernel_thread(struct qeth_card *card)
if (qeth_do_start_thread(card, QETH_SET_IP_THREAD)) if (qeth_do_start_thread(card, QETH_SET_IP_THREAD))
kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD); kernel_thread(qeth_register_ip_addresses, (void *)card,SIGCHLD);
if (qeth_do_start_thread(card, QETH_SET_PROMISC_MODE_THREAD))
kernel_thread(qeth_set_promisc_mode, (void *)card, SIGCHLD);
if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) if (qeth_do_start_thread(card, QETH_RECOVER_THREAD))
kernel_thread(qeth_recover, (void *) card, SIGCHLD); kernel_thread(qeth_recover, (void *) card, SIGCHLD);
} }
...@@ -5003,6 +5026,10 @@ qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *, ...@@ -5003,6 +5026,10 @@ qeth_default_setassparms_cb(struct qeth_card *, struct qeth_reply *,
unsigned long); unsigned long);
static int static int
qeth_default_setadapterparms_cb(struct qeth_card *card,
struct qeth_reply *reply,
unsigned long data);
static int
qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *,
__u16, long, __u16, long,
int (*reply_cb) int (*reply_cb)
...@@ -5476,6 +5503,59 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) ...@@ -5476,6 +5503,59 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
qeth_set_multicast_list(card->dev); qeth_set_multicast_list(card->dev);
} }
#endif #endif
/**
* Examine hardware response to SET_PROMISC_MODE
*/
static int
qeth_setadp_promisc_mode_cb(struct qeth_card *card,
struct qeth_reply *reply,
unsigned long data)
{
struct qeth_ipa_cmd *cmd;
struct qeth_ipacmd_setadpparms *setparms;
QETH_DBF_TEXT(trace,4,"prmadpcb");
cmd = (struct qeth_ipa_cmd *) data;
setparms = &(cmd->data.setadapterparms);
qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
if (cmd->hdr.return_code) {
QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
setparms->data.mode = SET_PROMISC_MODE_OFF;
}
card->info.promisc_mode = setparms->data.mode;
return 0;
}
/*
* Set promiscuous mode (on or off) (SET_PROMISC_MODE command)
*/
static void
qeth_setadp_promisc_mode(struct qeth_card *card)
{
enum qeth_ipa_promisc_modes mode;
struct net_device *dev = card->dev;
struct qeth_cmd_buffer *iob;
struct qeth_ipa_cmd *cmd;
QETH_DBF_TEXT(trace, 4, "setprom");
if (((dev->flags & IFF_PROMISC) &&
(card->info.promisc_mode == SET_PROMISC_MODE_ON)) ||
(!(dev->flags & IFF_PROMISC) &&
(card->info.promisc_mode == SET_PROMISC_MODE_OFF)))
return;
mode = SET_PROMISC_MODE_OFF;
if (dev->flags & IFF_PROMISC)
mode = SET_PROMISC_MODE_ON;
QETH_DBF_TEXT_(trace, 4, "mode:%x", mode);
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_PROMISC_MODE,
sizeof(struct qeth_ipacmd_setadpparms));
cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
cmd->data.setadapterparms.data.mode = mode;
qeth_send_ipa_cmd(card, iob, qeth_setadp_promisc_mode_cb, NULL);
}
/** /**
* set multicast address on card * set multicast address on card
...@@ -5501,6 +5581,11 @@ qeth_set_multicast_list(struct net_device *dev) ...@@ -5501,6 +5581,11 @@ qeth_set_multicast_list(struct net_device *dev)
out: out:
if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
schedule_work(&card->kernel_thread_starter); schedule_work(&card->kernel_thread_starter);
if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
return;
if (qeth_set_thread_start_bit(card, QETH_SET_PROMISC_MODE_THREAD)==0)
schedule_work(&card->kernel_thread_starter);
} }
static int static int
...@@ -6510,6 +6595,8 @@ qeth_default_setadapterparms_cb(struct qeth_card *card, ...@@ -6510,6 +6595,8 @@ qeth_default_setadapterparms_cb(struct qeth_card *card,
return 0; return 0;
} }
static int static int
qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply, qeth_query_setadapterparms_cb(struct qeth_card *card, struct qeth_reply *reply,
unsigned long data) unsigned long data)
...@@ -6676,6 +6763,12 @@ qeth_layer2_initialize(struct qeth_card *card) ...@@ -6676,6 +6763,12 @@ qeth_layer2_initialize(struct qeth_card *card)
QETH_DBF_TEXT(setup, 2, "doL2init"); QETH_DBF_TEXT(setup, 2, "doL2init");
QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card)); QETH_DBF_TEXT_(setup, 2, "doL2%s", CARD_BUS_ID(card));
rc = qeth_query_setadapterparms(card);
if (rc) {
PRINT_WARN("could not query adapter parameters on device %s: "
"x%x\n", CARD_BUS_ID(card), rc);
}
rc = qeth_setadpparms_change_macaddr(card); rc = qeth_setadpparms_change_macaddr(card);
if (rc) { if (rc) {
PRINT_WARN("couldn't get MAC address on " PRINT_WARN("couldn't get MAC address on "
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <asm/qeth.h> #include <asm/qeth.h>
#define VERSION_QETH_MPC_H "$Revision: 1.43 $" #define VERSION_QETH_MPC_H "$Revision: 1.44 $"
extern const char *VERSION_QETH_MPC_C; extern const char *VERSION_QETH_MPC_C;
...@@ -217,7 +217,7 @@ enum qeth_ipa_setadp_cmd { ...@@ -217,7 +217,7 @@ enum qeth_ipa_setadp_cmd {
IPA_SETADP_SEND_OSA_MESSAGE = 0x0100, IPA_SETADP_SEND_OSA_MESSAGE = 0x0100,
IPA_SETADP_SET_SNMP_CONTROL = 0x0200, IPA_SETADP_SET_SNMP_CONTROL = 0x0200,
IPA_SETADP_READ_SNMP_PARMS = 0x0400, IPA_SETADP_READ_SNMP_PARMS = 0x0400,
IPA_SETADP_WRITE_SNMP_PARMS = 0x0800, IPA_SETADP_SET_PROMISC_MODE = 0x0800,
IPA_SETADP_QUERY_CARD_INFO = 0x1000, IPA_SETADP_QUERY_CARD_INFO = 0x1000,
}; };
enum qeth_ipa_mac_ops { enum qeth_ipa_mac_ops {
...@@ -232,9 +232,12 @@ enum qeth_ipa_addr_ops { ...@@ -232,9 +232,12 @@ enum qeth_ipa_addr_ops {
CHANGE_ADDR_ADD_ADDR = 1, CHANGE_ADDR_ADD_ADDR = 1,
CHANGE_ADDR_DEL_ADDR = 2, CHANGE_ADDR_DEL_ADDR = 2,
CHANGE_ADDR_FLUSH_ADDR_TABLE = 4, CHANGE_ADDR_FLUSH_ADDR_TABLE = 4,
}; };
enum qeth_ipa_promisc_modes {
SET_PROMISC_MODE_OFF = 0,
SET_PROMISC_MODE_ON = 1,
};
/* (SET)DELIP(M) IPA stuff ***************************************************/ /* (SET)DELIP(M) IPA stuff ***************************************************/
struct qeth_ipacmd_setdelip4 { struct qeth_ipacmd_setdelip4 {
__u8 ip_addr[4]; __u8 ip_addr[4];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment